PHP usort自定义列表

时间:2018-08-14 21:34:08

标签: php arrays sorting

我有以下数组。我正在尝试按一堆自定义值对其进行排序。

Array
(
    [0] => Array
        (
            [item] => 'apple'
            [quality] => 3
            [store] => 'freds'
            [price] => 2
        )

    [1] => Array
        (
            [item] => 'pear'
            [quality] => 1
            [store] => 'bobs'
            [price] => 3
        )
    [2] => Array
        (
            [item] => 'banana'
            [quality] => 2
            [store] => 'freds'
            [price] => 1
        )
    [3] => Array
        (
            [item] => 'kiwi'
            [quality] => 2
            [store] => 'sams'
            [price] => 4
        )
    [4] => Array
        (
            [item] => 'coconut'
            [quality] => 2
            [store] => 'sams'
            [price] => 6
        )
    [5] => Array
        (
            [item] => 'lime'
            [quality] => 3
            [store] => 'sams'
            [price] => 5
        )
) 

请先按质量进行排序,然后再按最低编号排序。 如果质量相同,则从该自定义数组中按存储顺序对存储进行排序。因此它将bob放在第一位,而sam放在第二位,等等。

Array(0=>'bobs',1=>'sams',2=>'freds')

然后,如果是同一家商店,则按照价格从高到低的顺序排序。

所以数组应该是

[1] => Array
        (
            [item] => 'pear'
            [quality] => 1
            [store] => 'bobs'
            [price] => 3
        )
[2] => Array
        (
            [item] => 'coconut'
            [quality] => 2
            [store] => 'sams'
            [price] => 6
        )
[3] => Array
        (
            [item] => 'kiwi'
            [quality] => 2
            [store] => 'sams'
            [price] => 4
        )
[4] => Array
        (
            [item] => 'banana'
            [quality] => 2
            [store] => 'freds'
            [price] => 1
        )
[5] => Array
        (
            [item] => 'lime'
            [quality] => 3
            [store] => 'sams'
            [price] => 5
        )
[6] => Array
        (
            [item] => 'apple'
            [quality] => 3
            [store] => 'freds'
            [price] => 2
        )

我尝试了很多不同的组合,但无法弄清楚。是否可以仅使用usort,还是我需要手动循环遍历数组并从中找出来?

4 个答案:

答案 0 :(得分:0)

受到此答案的启发,该答案部分涵盖了您的问题:https://stackoverflow.com/a/4582659/2377164

您可以先按质量ASC订购,然后按PRICE DESC

<span tooltip="hello" [isDisabled]="false">
    <button type="button" class="btn btn-primary" disabled>
        <i class="fa fa-book-open"></i> btn disabled
    </button>
</span>

然后您可以通过自定义数组在内部订购:

<?php

$toto = [
 0 => [
   "item" => 'apple',
   "quality" => 3,
   "store" => 'freds',
   "price" => 2,
 ],
 1 => [
   "item" => 'pear',
   "quality" => 1,
   "store" => 'bobs',
   "price" => 3,
 ],
 2 => [
   "item" => 'banana',
   "quality" => 2,
   "store" => 'freds',
   "price" => 1,
 ],
 3 => [
   "item" => 'kiwi',
   "quality" => 2,
   "store" => 'sams',
   "price" => 4,
 ],
 4 => [
   "item" => 'coconut',
   "quality" => 2,
   "store" => 'sams',
   "price" => 6,
 ],
 5 => [
  "item" => 'lime',
  "quality" => 3,
  "store" => 'sams',
  "price" => 5,
 ],
];

array_multisort(
  array_column($toto, 'quality'), SORT_ASC,
  array_column($toto, 'price'), SORT_DESC,
  $toto
);

因此无需循环,您的最终脚本将是

usort($toto, function ($pr, $nx) {
$comp = [0 => 'bobs', 1 => 'freds', 2 => 'sams'];
$flipped = array_flip($comp);

return 
    $pr['quality'] === $nx['quality'] && 
    $flipped[$pr['store']] > $flipped[$nx['store']];
});

var_dump($toto);

array_multisort( array_column($toto, 'quality'), SORT_ASC, array_column($toto, 'price'), SORT_DESC, $toto); usort($toto, function ($pr, $nx) { $comp = [0 => 'bobs', 1 => 'freds', 2 => 'sams']; $flipped = array_flip($comp); return $pr['quality'] === $nx['quality'] && $flipped[$pr['store']] > $flipped[$nx['store']]; }); 是您的数组

将为您提供自定义的$toto

Array(0=>'bobs',1=>'sams',2=>'freds')

还有自定义数组array(6) { [0] => array(4) { 'item' => string(4) "pear" 'quality' => int(1) 'store' => string(4) "bobs" 'price' => int(3) } [1] => array(4) { 'item' => string(7) "coconut" 'quality' => int(2) 'store' => string(4) "sams" 'price' => int(6) } [2] => array(4) { 'item' => string(4) "kiwi" 'quality' => int(2) 'store' => string(4) "sams" 'price' => int(4) } [3] => array(4) { 'item' => string(6) "banana" 'quality' => int(2) 'store' => string(5) "freds" 'price' => int(1) } [4] => array(4) { 'item' => string(4) "lime" 'quality' => int(3) 'store' => string(4) "sams" 'price' => int(5) } [5] => array(4) { 'item' => string(5) "apple" 'quality' => int(3) 'store' => string(5) "freds" 'price' => int(2) } }

Array(0=>'bobs',1=>'freds',2=>'sams')

我认为它可以满足您的需求。

某些文档: http://php.net/manual/en/function.array-multisort.php

http://php.net/manual/en/function.array-column.php

答案 1 :(得分:0)

usort可以做到。只需在比较器中输入所有需求,然后使用array_flip使商店订购进入快速查找表即可。

$data = [
  [
    "item" => 'apple',
    "quality" => 3,
    "store" => 'freds',
    "price" => 2
  ],
  [
    "item" => 'pear',
    "quality" => 1,
    "store" => 'bobs',
    "price" => 3
  ],
  [
    "item" => 'banana',
    "quality" => 2,
    "store" => 'freds',
    "price" => 1
  ],
  [
    "item" => 'kiwi',
    "quality" => 2,
    "store" => 'sams',
    "price" => 4
  ],
  [
    "item" => 'coconut',
    "quality" => 2,
    "store" => 'sams',
    "price" => 6,
  ],
  [
    "item" => 'lime',
    "quality" => 3,
    "store" => 'sams',
    "price" => 5
  ]
];

$stores = array_flip(['bobs', 'sams', 'freds']);

usort($data, function ($a, $b) {
    global $stores;

    if ($a['quality'] === $b['quality']) {
        if ($stores[$a['store']] === $stores[$b['store']]) {
            return $b['price'] - $a['price'];
        }
        else {
            return $stores[$a['store']] > $stores[$b['store']];
        }
    }

    return $a['quality'] - $b['quality'];
});

print_r($data);

输出:

Array
(
    [0] => Array
        (
            [item] => pear
            [quality] => 1
            [store] => bobs
            [price] => 3
        )

    [1] => Array
        (
            [item] => coconut
            [quality] => 2
            [store] => sams
            [price] => 6
        )

    [2] => Array
        (
            [item] => kiwi
            [quality] => 2
            [store] => sams
            [price] => 4
        )

    [3] => Array
        (
            [item] => banana
            [quality] => 2
            [store] => freds
            [price] => 1
        )

    [4] => Array
        (
            [item] => lime
            [quality] => 3
            [store] => sams
            [price] => 5
        )

    [5] => Array
        (
            [item] => apple
            [quality] => 3
            [store] => freds
            [price] => 2
        )

)

还有一个repl可以尝试。

答案 2 :(得分:0)

绝对可以使用usort进行任何排序,因为它允许用户/开发人员定义排序方式。

以下是带有可调用函数的usort:

usort($data, function ($a,$b){
if($a['quality']==$b['quality']){
     if($a['store']==$b['store']){
          if($a['price']==$b['price']){
              return 0;
          }else{
              return $a['price']>$b['price']?-1:1;//Sort by price higher to lower i.e. Descending
          }
     }else{
              return $a['store']<$b['store']?-1:1;//Sort by store lower to higher i.e. Ascending
     }
}else{
              return $a['quality']<$b['quality']?-1:1;//Sort by quality lower to higher i.e. Ascending
}
});

var_dump($data);

检查代码并在以下位置输出:https://3v4l.org/CD2qE

说明:

与数组一起使用时,它使用可调用函数对数组中的每两个元素进行比较。 可调用函数应根据用户/开发人员希望对元素进行排序的方式返回1、0或-1。

  1. 如果要比较的元素的位置不变,则可调用函数应返回0

  2. 如果要在另一个元素之前放置,则可调用函数应返回-1

  3. 如果要在另一个元素之后放置,则可调用函数应返回1

参考: http://php.net/manual/en/function.usort.php

答案 3 :(得分:0)

您将使用array_flip通过商店名称访问$ stores数组以获取数字键,然后使用usort函数定义条件以将数组返回到预期输出。

> 在此示例中,

$ array将是存储数组变量的任何内容,因此请进行相应调整:

$stores = array_flip(['bobs', 'sams', 'freds']);
usort($array, function($a, $b) use ($stores) {
    $quality = $a['quality'] == $b['quality'];
    $store = $a['store'] == $b['store'];

    if ($quality && $store): return $a['price'] < $b['price'];
    elseif ($quality && !$store): return $stores[$a['store']] > $stores[$b['store']];
    else: return $a['quality'] > $b['quality'];
    endif;
});