PHP - 按另一个数组对多维数组进行排序

发布于 2024-12-10 09:45:55 字数 737 浏览 0 评论 0原文

我正在尝试按另一个数组对多维数组进行排序,但到目前为止还不够。
array_multisort 似乎仅适用于真正的排序。

假设我有这 2 个数组:

$order = array(2,3,1);

$data = array(
    array('id' => 1, 'title' => 'whatever'),
    array('id' => 2, 'title' => 'whatever'),
    array('id' => 3, 'title' => 'whatever')
);

现在我想根据 $order 数组中的顺序对 $data 数组进行排序。
这就是我希望的结果:

$data = array(
    array('id' => 2, 'title' => 'whatever'),
    array('id' => 3, 'title' => 'whatever')
    array('id' => 1, 'title' => 'whatever'),
);

我可以通过运行嵌套循环轻松完成此任务,但这不能很好地扩展(我的数组非常大,并且数组有更多字段)。

I'm trying to sort a multi-dimensional array by another array, but have so far come up short.
array_multisort seems be working only for real sorting.

Suppose I have these 2 arrays:

$order = array(2,3,1);

$data = array(
    array('id' => 1, 'title' => 'whatever'),
    array('id' => 2, 'title' => 'whatever'),
    array('id' => 3, 'title' => 'whatever')
);

Now I would like to sort my $data array according to the order in my $order array.
This is what I would like the result to be:

$data = array(
    array('id' => 2, 'title' => 'whatever'),
    array('id' => 3, 'title' => 'whatever')
    array('id' => 1, 'title' => 'whatever'),
);

I can accomplish this easily by running a nested loop, but that would not scale well (my array is pretty big, and the arrays have many more fields).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

绻影浮沉 2024-12-17 09:45:55

在您的示例中,$data 数组中的 id 是连续编号的,并从 1 开始。下面给出的代码假设情况总是如此。如果不是这种情况,则该代码不起作用。

$result = array();
$index = 0;
foreach ($order as $position) {
    $result[$index] = $data[$position - 1];
    $index++;
}

http://codepad.org/YC8w0yHh 您可以看到它适用于您的示例数据。

编辑

如果上述假设不成立,则以下代码将达到相同的结果:

<?php

$data = array(
    array('id' => 1, 'title' => 'whatever'),
    array('id' => 2, 'title' => 'whatever'),
    array('id' => 3, 'title' => 'whatever')
);

$order = array(2,3,1);
$order = array_flip($order);

function cmp($a, $b)
{
    global $order;

    $posA = $order[$a['id']];
    $posB = $order[$b['id']];

    if ($posA == $posB) {
        return 0;
    }
    return ($posA < $posB) ? -1 : 1;
}

usort($data, 'cmp');

var_dump($data);

请参阅http: //codepad.org/Q7EcTSfs 作为证明。

通过在 $order 数组上调用 array_flip() ,它可以用于位置查找。这就像哈希表查找,在时间上是线性的,即 O(n)。你不能做得更好。

In your example the ids in the $data array are are numbered consecutively and starting at 1. The code I give below assumes this is always the case. If this is not the case, the code does not work.

$result = array();
$index = 0;
foreach ($order as $position) {
    $result[$index] = $data[$position - 1];
    $index++;
}

At http://codepad.org/YC8w0yHh you can see that it works for your example data.

EDIT

If the assumption mentioned above does not hold, the following code will achieve the same result:

<?php

$data = array(
    array('id' => 1, 'title' => 'whatever'),
    array('id' => 2, 'title' => 'whatever'),
    array('id' => 3, 'title' => 'whatever')
);

$order = array(2,3,1);
$order = array_flip($order);

function cmp($a, $b)
{
    global $order;

    $posA = $order[$a['id']];
    $posB = $order[$b['id']];

    if ($posA == $posB) {
        return 0;
    }
    return ($posA < $posB) ? -1 : 1;
}

usort($data, 'cmp');

var_dump($data);

See http://codepad.org/Q7EcTSfs for proof.

By calling array_flip() on the $order array it can be used for position lookup. This is like a hashtable lookup, which is linear in time, or O(n). You cannot do better.

萌吟 2024-12-17 09:45:55

对于那些想要基于具有实际 ID 的数组而不是像已接受的答案中那样基于具有索引的数组对数据进行排序的人,您可以对 usort 使用以下简单的比较函数:

usort($data, function($a, $b) use ($order) {
    $posA = array_search($a['id'], $order);
    $posB = array_search($b['id'], $order);
    return $posA - $posB;
});

因此,以下示例将正常工作,并且您不会收到 Undefined offset 通知和具有 null 值的数组:

$order = [20, 30, 10];

$data = [
    ['id' => 10, 'title' => 'Title 1'],
    ['id' => 20, 'title' => 'Title 2'],
    ['id' => 30, 'title' => 'Title 3']
];

usort($data, function($a, $b) use ($order) {
    $posA = array_search($a['id'], $order);
    $posB = array_search($b['id'], $order);
    return $posA - $posB;
});

echo '<pre>', var_dump($data), '</pre>';

输出:

array(3) {
  [0]=>
  array(2) {
    ["id"]=>
    int(20)
    ["title"]=>
    string(7) "Title 2"
  }
  [1]=>
  array(2) {
    ["id"]=>
    int(30)
    ["title"]=>
    string(7) "Title 3"
  }
  [2]=>
  array(2) {
    ["id"]=>
    int(10)
    ["title"]=>
    string(7) "Title 1"
  }
}

For those of you who want to sort data based on an array with actual IDs, rather than based on an array with indexes like in the accepted answer - you can use the following simple comparison function for the usort:

usort($data, function($a, $b) use ($order) {
    $posA = array_search($a['id'], $order);
    $posB = array_search($b['id'], $order);
    return $posA - $posB;
});

So the following example will work fine and you won't get the Undefined offset notices and an array with null values:

$order = [20, 30, 10];

$data = [
    ['id' => 10, 'title' => 'Title 1'],
    ['id' => 20, 'title' => 'Title 2'],
    ['id' => 30, 'title' => 'Title 3']
];

usort($data, function($a, $b) use ($order) {
    $posA = array_search($a['id'], $order);
    $posB = array_search($b['id'], $order);
    return $posA - $posB;
});

echo '<pre>', var_dump($data), '</pre>';

Output:

array(3) {
  [0]=>
  array(2) {
    ["id"]=>
    int(20)
    ["title"]=>
    string(7) "Title 2"
  }
  [1]=>
  array(2) {
    ["id"]=>
    int(30)
    ["title"]=>
    string(7) "Title 3"
  }
  [2]=>
  array(2) {
    ["id"]=>
    int(10)
    ["title"]=>
    string(7) "Title 1"
  }
}
鹿童谣 2024-12-17 09:45:55

PHP 中没有用于此目的的内置函数,我无法想到任何自定义函数可以使用 usort 来执行此操作。但在我看来,array_map 已经足够简单了,那么为什么不使用它呢?

$sorted = array_map(function($v) use ($data) {
    return $data[$v - 1];
}, $order);

There is no built-in function for this in PHP and i am unable to think of any custom function, which would do this using usort. But array_map is simple enough, imo, so why not use it instead?

$sorted = array_map(function($v) use ($data) {
    return $data[$v - 1];
}, $order);
稚然 2024-12-17 09:45:55

我就会这么做。我将使用自定义 usort 函数 (arr_sort) 与 $data 数组结合使用。

<?php
$order = array(2,3,1);
$data = array(
    array('id' => 1, 'title' => 'whatever'),
    array('id' => 2, 'title' => 'whatever'),
    array('id' => 3, 'title' => 'whatever')
);
function arr_sort($a,$b){
  global $order;
  foreach ($order as $key => $value) {
    if ($value==$a['id']) {
      return 0;
      break;
    }
    if ($value==$b['id']) {
      return 1;
      break;
    }
  }
}
usort($data,'arr_sort');
echo "<pre>";
print_r($data);
echo "<pre>";

This would be how I would do. I would use a custom usort function (arr_sort) in conjunction with the $data array.

<?php
$order = array(2,3,1);
$data = array(
    array('id' => 1, 'title' => 'whatever'),
    array('id' => 2, 'title' => 'whatever'),
    array('id' => 3, 'title' => 'whatever')
);
function arr_sort($a,$b){
  global $order;
  foreach ($order as $key => $value) {
    if ($value==$a['id']) {
      return 0;
      break;
    }
    if ($value==$b['id']) {
      return 1;
      break;
    }
  }
}
usort($data,'arr_sort');
echo "<pre>";
print_r($data);
echo "<pre>";
安人多梦 2024-12-17 09:45:55

您可以尝试使用 usort() 进行自定义排序。这样您就可以使用第一个数组来确定第二个数组的顺序。

You could try using a custom sort with usort(). This way you can use the first array to determine the order of the second array.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文