Jak posortować tablicę tablic asocjacyjnych według wartości danego klucza w PHP?

Podano tablicę:

$inventory = array(

   array("type"=>"fruit", "price"=>3.50),
   array("type"=>"milk", "price"=>2.90),
   array("type"=>"pork", "price"=>5.43),

);

Chciałbym posortować $inventory elementy według ceny aby otrzymać:

$inventory = array(

   array("type"=>"pork", "price"=>5.43),
   array("type"=>"fruit", "price"=>3.50),
   array("type"=>"milk", "price"=>2.90),

);
Jak mogę to zrobić?
 313
Author: Mark Amery, 2009-10-21

16 answers

Masz rację, funkcja, której szukasz to array_multisort().

Oto przykład zaczerpnięty prosto z podręcznika i dostosowany do twojego przypadku:

$price = array();
foreach ($inventory as $key => $row)
{
    $price[$key] = $row['price'];
}
array_multisort($price, SORT_DESC, $inventory);
 448
Author: Josh Davis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-20 15:40:47

PHP 7 +

Począwszy od PHP 7, można to zrobić zwięźle za pomocą usort z funkcją anonimową , która wykorzystuje operator statku kosmicznego do porównywania elementów.

Możesz zrobić coś takiego:

usort($inventory, function ($item1, $item2) {
    return $item1['price'] <=> $item2['price'];
});

Lub malejąco tak:

usort($inventory, function ($item1, $item2) {
    return $item2['price'] <=> $item1['price'];
});

Aby zrozumieć, jak to działa, zauważ, że usort pobiera funkcję porównawczą dostarczoną przez użytkownika, która musi zachowywać się w następujący sposób (z dokumentów): {]}

Porównanie funkcja musi zwracać liczbę całkowitą mniejszą niż, równą lub większą niż zero, jeśli pierwszy argument jest odpowiednio mniejszy niż, równy lub większy niż drugi.

I zauważ również, że <=>, Operator statku kosmicznego,

Zwraca 0, jeśli oba operandy są równe, 1, jeśli lewa jest większa, i -1, jeśli prawa jest większa

Tego właśnie potrzebuje usort. Faktycznie, prawie całe uzasadnienie podane dla dodania <=> do język w https://wiki.php.net/rfc/combined-comparison-operator jest to

Sprawia, że pisanie wywołań zwrotnych do użytku z usort() jest łatwiejsze


PHP 5.3 +

PHP 5.3 wprowadził funkcje anonimowe, ale nie ma jeszcze operatora statku kosmicznego. Możemy nadal używać usort do sortowania naszej tablicy, ale jest to trochę bardziej gadatliwe i trudniejsze do zrozumienia: {]}

usort($inventory, function ($item1, $item2) {
    if ($item1['price'] == $item2['price']) return 0;
    return $item1['price'] < $item2['price'] ? -1 : 1;
});

Zauważ, że chociaż jest to dość powszechne dla komparatorów zajmujących się liczbą całkowitą wartości aby po prostu zwrócić różnicę wartości, jak $item2['price'] - $item1['price'], my nie możemy bezpiecznie to zrobić w tym przypadku. Dzieje się tak, ponieważ ceny są liczbami zmiennoprzecinkowymi w przykładzie pytającego, ale funkcja porównawcza, którą przekazujemy usort, musi zwracać liczby całkowite dla usort, aby działać poprawnie:

Powrót non-integer wartości z funkcji porównawczej, takie jak float, spowodują wewnętrzny rzut do liczby całkowitej wartości zwrotnej wywołania zwrotnego. Więc wartości takie jak 0.99 i 0.1 zostaną oddane do wartości całkowitej 0, która porównuje takie wartości jako równe.

Jest to ważna pułapka, o której należy pamiętać podczas używania usort w PHP 5.x! moja Oryginalna wersja tej odpowiedzi popełniła ten błąd, a mimo to zgromadziłam 10 głosów ponad tysiąc wyświetleń najwyraźniej bez zauważenia poważnego błędu. Łatwość, z jaką lackwits jak ja może spieprzyć funkcje komparatora jest właśnie powodem, dla którego łatwiejszy w użyciu Operator został dodany do języka w PHP 7.

 189
Author: Mark Amery,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:17

Ponieważ twoje elementy tablicy są same w sobie tablicami z kluczami łańcuchowymi, najlepszym rozwiązaniem jest zdefiniowanie niestandardowej funkcji porównywania. Jest to dość szybkie i łatwe do zrobienia. Spróbuj tego:

function invenDescSort($item1,$item2)
{
    if ($item1['price'] == $item2['price']) return 0;
    return ($item1['price'] < $item2['price']) ? 1 : -1;
}
usort($inventory,'invenDescSort');
print_r($inventory);

Produkuje:

Array
(
    [0] => Array
        (
            [type] => pork
            [price] => 5.43
        )

    [1] => Array
        (
            [type] => fruit
            [price] => 3.5
        )

    [2] => Array
        (
            [type] => milk
            [price] => 2.9
        )

)
 39
Author: zombat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-20 23:04:35

Podczas gdy inni poprawnie zasugerowali użycie array_multisort(), z jakiegoś powodu żadna odpowiedź nie zdaje się potwierdzać istnienia array_column(), co może znacznie uprościć rozwiązanie. Więc moja propozycja to:

array_multisort(array_column($inventory, 'price'), SORT_DESC, $inventory);
 30
Author: Mariano Iglesias,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-28 21:04:19

Skończyłem na tym:

function sort_array_of_array(&$array, $subfield)
{
    $sortarray = array();
    foreach ($array as $key => $row)
    {
        $sortarray[$key] = $row[$subfield];
    }

    array_multisort($sortarray, SORT_ASC, $array);
}

Wystarczy wywołać funkcję, przekazując tablicę i nazwę pola tablicy drugiego poziomu. Like:

sort_array_of_array($inventory, 'price');
 21
Author: Danielzt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-19 15:18:23

Możesz użyć usort z funkcją anonimową, np.

usort($inventory, function ($a, $b) { return strnatcmp($a['price'], $b['price']); });
 12
Author: kenorb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-30 16:16:09
$inventory = 
    array(array("type"=>"fruit", "price"=>3.50),
          array("type"=>"milk", "price"=>2.90),
          array("type"=>"pork", "price"=>5.43),
          );

function pricesort($a, $b) {
  $a = $a['price'];
  $b = $b['price'];
  if ($a == $b)
    return 0;
  return ($a > $b) ? -1 : 1;
}

usort($inventory, "pricesort");
// uksort($inventory, "pricesort");

print("first: ".$inventory[0]['type']."\n\n");
// for usort(): prints milk (item with lowest price)
// for uksort(): prints fruit (item with key 0 in the original $inventory)

// foreach prints the same for usort and uksort.
foreach($inventory as $i){
  print($i['type'].": ".$i['price']."\n");
}

Wyjścia:

first: pork

pork: 5.43
fruit: 3.5
milk: 2.9
 8
Author: danamlund,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-20 23:16:21

Został przetestowany na 100 000 płytach: Czas w sekundach (liczony przez funciton microtime). tylko dla unikalnych wartości na sortowaniu kluczowych pozycji.

Rozwiązanie funkcji @ Josh Davis: : 1.5768740177155

Rozwiązanie kopalni: : 0.094044923782349

Rozwiązanie:

function SortByKeyValue($data, $sortKey, $sort_flags=SORT_ASC)
{
    if (empty($data) or empty($sortKey)) return $data;

    $ordered = array();
    foreach ($data as $key => $value)
        $ordered[$value[$sortKey]] = $value;

    ksort($ordered, $sort_flags);

    return array_values($ordered); *// array_values() added for identical result with multisort*
}
 3
Author: Nefelim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-15 11:39:33

Możesz spróbować zdefiniować własną funkcję porównawczą, a następnie użyć usort.

 1
Author: Alex Sexton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-10-20 23:07:00

Ta funkcja jest wielokrotnego użytku:

function usortarr(&$array, $key, $callback = 'strnatcasecmp') {
    uasort($array, function($a, $b) use($key, $callback) {
        return call_user_func($callback, $a[$key], $b[$key]);
    });
}

To działa dobrze na wartościach ciągów domyślnie, ale będziesz musiał sub wywołania zwrotnego dla funkcja porównywania liczb jeśli wszystkie wartości są liczbami.

 1
Author: mpen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:17

Od Sortuj tablicę tablic asocjacyjnych według wartości podanego klucza w php:

Uasort ( http://php.net/uasort ) pozwala na sortowanie tablicy według własnej zdefiniowanej funkcji. W Twoim przypadku to proste:

$array = array(
  array('price'=>'1000.50','product'=>'test1'),
  array('price'=>'8800.50','product'=>'test2'),
  array('price'=>'200.0','product'=>'test3')
);

function cmp($a, $b) {
  return $a['price'] > $b['price'];
}

uasort($array, "cmp");
 1
Author: Kamal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-11 21:04:48
//Just in one line custom function
function cmp($a, $b)
{
return (float) $a['price'] < (float)$b['price'];
}
@uasort($inventory, "cmp");
print_r($inventory);

//result

Array
(
[2] => Array
    (
        [type] => pork
        [price] => 5.43
    )

[0] => Array
    (
        [type] => fruit
        [price] => 3.5
    )

[1] => Array
    (
        [type] => milk
        [price] => 2.9
    )

)
 0
Author: Kamal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-20 07:15:24

Pełna Funkcja Dynamiczna Przeskoczyłem tutaj dla asocjacyjnego sortowania tablic i znalazłem tę niesamowitą funkcję na http://php.net/manual/en/function.sort.php . Ta funkcja jest bardzo dynamiczna, która sortuje rosnąco i malejąco Po podanym kluczu.

Prosta funkcja sortowania tablicy według określonego klucza. Utrzymuje asocjację indeksu

<?php

function array_sort($array, $on, $order=SORT_ASC)
{
    $new_array = array();
    $sortable_array = array();

    if (count($array) > 0) {
        foreach ($array as $k => $v) {
            if (is_array($v)) {
                foreach ($v as $k2 => $v2) {
                    if ($k2 == $on) {
                        $sortable_array[$k] = $v2;
                    }
                }
            } else {
                $sortable_array[$k] = $v;
            }
        }

        switch ($order) {
            case SORT_ASC:
                asort($sortable_array);
            break;
            case SORT_DESC:
                arsort($sortable_array);
            break;
        }

        foreach ($sortable_array as $k => $v) {
            $new_array[$k] = $array[$k];
        }
    }

    return $new_array;
}

$people = array(
    12345 => array(
        'id' => 12345,
        'first_name' => 'Joe',
        'surname' => 'Bloggs',
        'age' => 23,
        'sex' => 'm'
    ),
    12346 => array(
        'id' => 12346,
        'first_name' => 'Adam',
        'surname' => 'Smith',
        'age' => 18,
        'sex' => 'm'
    ),
    12347 => array(
        'id' => 12347,
        'first_name' => 'Amy',
        'surname' => 'Jones',
        'age' => 21,
        'sex' => 'f'
    )
);

print_r(array_sort($people, 'age', SORT_DESC)); // Sort by oldest first
print_r(array_sort($people, 'surname', SORT_ASC)); // Sort by surname
 0
Author: Ahmad Sayeed,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-29 14:27:14
$arr1 = array(

    array('id'=>1,'name'=>'aA','cat'=>'cc'),
    array('id'=>2,'name'=>'aa','cat'=>'dd'),
    array('id'=>3,'name'=>'bb','cat'=>'cc'),
    array('id'=>4,'name'=>'bb','cat'=>'dd')
);

$result1 = array_msort($arr1, array('name'=>SORT_DESC);

$result2 = array_msort($arr1, array('cat'=>SORT_ASC);

$result3 = array_msort($arr1, array('name'=>SORT_DESC, 'cat'=>SORT_ASC));


function array_msort($array, $cols)
{
    $colarr = array();
    foreach ($cols as $col => $order) {
    $colarr[$col] = array();
    foreach ($array as $k => $row) { $colarr[$col]['_'.$k] = strtolower($row[$col]); }
}

$eval = 'array_multisort(';

foreach ($cols as $col => $order) {
    $eval .= '$colarr[\''.$col.'\'],'.$order.',';
}

$eval = substr($eval,0,-1).');';
eval($eval);
$ret = array();
foreach ($colarr as $col => $arr) {
    foreach ($arr as $k => $v) {
        $k = substr($k,1);
        if (!isset($ret[$k])) $ret[$k] = $array[$k];
        $ret[$k][$col] = $array[$k][$col];
    }
}
return $ret;


} 
 -1
Author: Chirag Pipariya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-19 15:19:41
  <?php

$inventory = array(

   array("type"=>"fruit", "price"=>3.50),
   array("type"=>"milk", "price"=>2.90),
   array("type"=>"pork", "price"=>5.43),

);



function myfunc($a,$b){
return strnatcmp($a['price'],$b['price']);
}
$result=usort ($inventory,"myfunc");?>
<pre><?php print_r(array_reverse($inventory)); ?></pre>

Proste rozwiązanie:)

Wyjście jest,

Array
(
    [0] => Array
        (
            [type] => pork
            [price] => 5.43
        )

    [1] => Array
        (
            [type] => fruit
            [price] => 3.5
        )

    [2] => Array
        (
            [type] => milk
            [price] => 2.9
        )

)
 -2
Author: Akhilhh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-04 05:22:38

Spróbuj tego:

asort($array_to_sort, SORT_NUMERIC);

W celach informacyjnych zobacz to: http://php.net/manual/en/function.asort.php

Zobacz różne flagi sortowania tutaj: http://www.php.net/manual/en/function.sort.php

 -3
Author: sarsnake,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-19 15:17:39