簡體   English   中英

如何按值對多維數組進行排序

[英]How to Sort a Multi-dimensional Array by Value

我如何根據“order”鍵的值對這個數組進行排序?

盡管這些值當前是連續的,但它們並不總是如此。

Array
(
    [0] => Array
        (
            [hashtag] => a7e87329b5eab8578f4f1098a152d6f4
            [title] => Flower
            [order] => 3
        )

    [1] => Array
        (
            [hashtag] => b24ce0cd392a5b0b8dedc66c25213594
            [title] => Free
            [order] => 2
        )

    [2] => Array
        (
            [hashtag] => e7d31fc0602fb2ede144d18cdffd816b
            [title] => Ready
            [order] => 1
        )
)

嘗試一個usort 如果您仍在使用 PHP 5.2 或更早版本,則必須先定義排序函數:

function sortByOrder($a, $b) {
    return $a['order'] - $b['order'];
}

usort($myArray, 'sortByOrder');

從 PHP 5.3 開始,您可以使用匿名函數:

usort($myArray, function($a, $b) {
    return $a['order'] - $b['order'];
});

最后,在 PHP 7 中,您可以使用spaceship 運算符

usort($myArray, function($a, $b) {
    return $a['order'] <=> $b['order'];
});

要將其擴展到多維排序,請在第一個排序元素為零時引用第二個/第三個排序元素 - 最好在下面解釋。 您還可以使用它對子元素進行排序。

usort($myArray, function($a, $b) {
    $retval = $a['order'] <=> $b['order'];
    if ($retval == 0) {
        $retval = $a['suborder'] <=> $b['suborder'];
        if ($retval == 0) {
            $retval = $a['details']['subsuborder'] <=> $b['details']['subsuborder'];
        }
    }
    return $retval;
});

如果您需要保留鍵關聯,請使用uasort() - 請參閱手冊中數組排序功能的比較

function aasort (&$array, $key) {
    $sorter = array();
    $ret = array();
    reset($array);
    foreach ($array as $ii => $va) {
        $sorter[$ii] = $va[$key];
    }
    asort($sorter);
    foreach ($sorter as $ii => $va) {
        $ret[$ii] = $array[$ii];
    }
    $array = $ret;
}

aasort($your_array, "order");

我使用這個功能:

function array_sort_by_column(&$arr, $col, $dir = SORT_ASC) {
    $sort_col = array();
    foreach ($arr as $key => $row) {
        $sort_col[$key] = $row[$col];
    }

    array_multisort($sort_col, $dir, $arr);
}

array_sort_by_column($array, 'order');

編輯此答案至少已有十年歷史,現在可能有更好的解決方案,但我正在根據幾條評論的要求添加一些額外信息。

它有效是因為array_multisort()可以對多個數組進行排序。 示例輸入:

Array
(
    [0] => Array
        (
            [hashtag] => a7e87329b5eab8578f4f1098a152d6f4
            [title] => Flower
            [order] => 3
        )

    [1] => Array
        (
            [hashtag] => b24ce0cd392a5b0b8dedc66c25213594
            [title] => Free
            [order] => 2
        )

首先創建$sort_col ,它是一個二維數組,其中的值是我們想要排序的,並且鍵匹配輸入數組。 例如對於這個輸入,選擇鍵$sort_col "order"我們得到:

Array
(
    [0] => 3,
    [1] => 2
)

array_multisort()然后對該數組進行排序(導致鍵順序為1, 0 ),但這只是二維數組。 所以原始輸入數組也作為$rest參數傳遞。 當鍵匹配時,它將被排序,所以它的鍵也按相同的順序,給出所需的結果。

筆記:

  • 它通過引用傳遞,以便就地修改提供的數組。
  • array_multisort()可以像這樣對多個附加數組進行排序,而不僅僅是一個

為了實現這一點,我們可以使用“array_multisort”方法“對多維或多維數組進行排序”。 它的方法參數是

  • $keys - 一個被排序的數組
  • SORT_ASC - 排序順序(升序)
  • 排序標志(通常比較項目(不要改變類型)或數字或字符串)
  • $new - 然后是其余的數組。 僅對應於前面的等效元素的元素
    數組進行比較。

'sort flags' 默認是 SORT_REGULAR,它被省略。

$new = [
    [
        'hashtag' => 'a7e87329b5eab8578f4f1098a152d6f4',
        'title' => 'Flower',
        'order' => 3,
    ],
    [
        'hashtag' => 'b24ce0cd392a5b0b8dedc66c25213594',
        'title' => 'Free',
        'order' => 2,
    ],
    [
        'hashtag' => 'e7d31fc0602fb2ede144d18cdffd816b',
        'title' => 'Ready',
        'order' => 1,
    ],
];
$keys = array_column($new, 'order');
array_multisort($keys, SORT_ASC, $new);
var_dump($new);

結果:

Array
(
    [0] => Array
        (
            [hashtag] => e7d31fc0602fb2ede144d18cdffd816b
            [title] => Ready
            [order] => 1
        )
    [1] => Array
        (
            [hashtag] => b24ce0cd392a5b0b8dedc66c25213594
            [title] => Free
            [order] => 2
        )
    [2] => Array
        (
            [hashtag] => a7e87329b5eab8578f4f1098a152d6f4
            [title] => Flower
            [order] => 3
        )
)

我通常使用usort ,並傳遞我自己的比較函數。 在這種情況下,它非常簡單:

function compareOrder($a, $b)
{
  return $a['order'] - $b['order'];
}
usort($array, 'compareOrder');

在 PHP 7 中使用 spaceship 運算符:

usort($array, function($a, $b) {
    return $a['order'] <=> $b['order'];
});

要按“title”鍵的值對數組進行排序,請使用:

uasort($myArray, function($a, $b) {
    return strcmp($a['title'], $b['title']);
});

strcmp比較字符串。

uasort()維護定義的數組鍵。

使用array_multisort() , array_map()

array_multisort(array_map(function($element) {
      return $element['order'];
  }, $array), SORT_ASC, $array);

print_r($array);

演示

$sort = array();
$array_lowercase = array_map('strtolower', $array_to_be_sorted);
array_multisort($array_lowercase, SORT_ASC, SORT_STRING, $alphabetically_ordered_array);

這會處理大寫和小寫字母。

正如接受的答案所述,您可以使用:

usort($myArray, function($a, $b) {
    return $a['order'] <=> $b['order'];
});

如果您需要按多列排序,那么您將執行以下操作:

usort($myArray, function($a, $b) {
    return [$a['column1'],$a['column2']] <=> [$b['column1'],$b['column2']];
});

這可以擴展到數據中的任意數量的列。 這取決於您可以直接比較 PHP 中的 arrays 的事實。 在上面的示例中,數組將首先按column1排序,然后按column2排序。 但是您可以按任何順序按列排序,例如:

usort($myArray, function($a, $b) {
    return [$a['column2'],$a['column1']] <=> [$b['column2'],$b['column1']];
});

如果您需要對一列進行升序和另一列降序排序,則將降序列交換到運算符<=>的另一側:

usort($myArray, function($a, $b) {
    return [$a['column1'],$b['column2']] <=> [$b['column1'],$a['column2']];
});

最靈活的方法是使用這種方法:

Arr::sortByKeys(array $array, $keys, bool $assoc = true): array

原因如下:

  • 您可以按任何鍵排序(也可以嵌套,如'key1.key2.key3'['k1', 'k2', 'k3']

  • 它適用於關聯數組和非關聯數組( $assoc標志)

  • 它不使用引用 - 它返回一個新的排序數組

在你的情況下,它會很簡單:

$sortedArray = Arr::sortByKeys($array, 'order');

這個方法是這個庫的一部分。

如果有人需要根據鍵進行排序,最好使用以下方法:

usort($array, build_sorter('order'));

function build_sorter($key) {
   return function ($a, $b) use ($key) {
      return strnatcmp($a[$key], $b[$key]);
   };
}

就這樣做,適用於7.4及更高版本

uasort($yourArray,fn($prev,$now)=>$prev['order']<=>$now['order']);

漂亮的印刷品

echo '<pre>';
print_r($yourArray);

此解決方案適用於 usort(),具有易於記憶的多維排序符號。 使用宇宙飛船運算符 <=>,可從 PHP 7 獲得。

usort($in,function($a,$b){
  return $a['first']   <=> $b['first']  //first asc
      ?: $a['second']  <=> $b['second'] //second asc
      ?: $b['third']   <=> $a['third']  //third desc (a b swapped!)
      //etc
  ;
});

例子:

$in = [
  ['firstname' => 'Anton', 'surname' => 'Gruber', 'birthdate' => '03.08.1967', 'rank' => 3],
  ['firstname' => 'Anna', 'surname' => 'Egger', 'birthdate' => '04.01.1960', 'rank' => 1],
  ['firstname' => 'Paul', 'surname' => 'Mueller', 'birthdate' => '15.10.1971', 'rank' => 2],
  ['firstname' => 'Marie', 'surname' => 'Schmidt ', 'birthdate' => '24.12.1963', 'rank' => 2],
  ['firstname' => 'Emma', 'surname' => 'Mueller', 'birthdate' => '23.11.1969', 'rank' => 2],
];

第一個任務:按職級升序,姓氏升序

usort($in,function($a,$b){
  return $a['rank']      <=> $b['rank']     //first asc
      ?: $a['surname']   <=> $b['surname']  //second asc
  ;
});

第二個任務:按等級降序、姓氏升序、姓氏升序排序

usort($in,function($a,$b){
  return $b['rank']      <=> $a['rank']       //first desc
      ?: $a['surname']   <=> $b['surname']    //second asc
      ?: $a['firstname'] <=> $b['firstname']  //third asc
  ;
});

第三個任務:Order By rank desc,生日升序

不能在此表示法中對日期進行排序。 它是用strtotime 轉換的。

usort($in,function($a,$b){
  return $b['rank']      <=> $a['rank']       //first desc
      ?: strtotime($a['birthdate']) <=> strtotime($b['birthdate'])    //second asc
  ;
});

您可以使用帶有回調函數的usort和用戶定義的排序函數:

usort($new, fn($a, $b) => $a['order'] - $b['order']);

技巧:您可以使用a > ba - ba <=> b進行升序排序。 對於降序,只是ab的交換位置。

讓我們面對現實吧:PHP沒有一個簡單外的存儲箱功能,妥善處理每一個數組排序情況。

這個例程很直觀,這意味着更快的調試和維護:

// Automatic population of the array
$tempArray = array();
$annotations = array();
// ... some code
// SQL $sql retrieves result array $result
// $row[0] is the ID, but is populated out of order (comes from
// multiple selects populating various dimensions for the same DATE
// for example
while($row = mysql_fetch_array($result)) {
    $needle = $row[0];
    arrayIndexes($needle);  // Create a parallel array with IDs only
    $annotations[$needle]['someDimension'] = $row[1]; // Whatever
}
asort($tempArray);
foreach ($tempArray as $arrayKey) {
    $dataInOrder = $annotations[$arrayKey]['someDimension'];
    // .... more code
}

function arrayIndexes ($needle) {
    global $tempArray;
    if (!in_array($needle, $tempArray)) {
        array_push($tempArray, $needle);
    }
}

我發現這很有幫助:

    $columns = array_column($data, "order");
    array_multisort($columns, SORT_ASC, $data);

按名稱升序排序

 example  with class:
 
 class user
 {
     private $key;

     public function __construct(string $key)
     {
         $this->key = $key;
     }

     public function __invoke($a, $b)
     {
         return $a[$this->key] <=> $b[$this->key];
     }
 }

 $user = [
     ['id' => 1, 'name' => 'Oliver', 'id_card' => 4444],
     ['id' => 3, 'name' => 'Jack', 'id_card' => 5555],
     ['id' => 2, 'name' => 'Harry', 'id_card' => 6666]
 ];

 // sort user by id
 usort($user, new user('id'));
 var_dump($user);

另一個基於相同邏輯的 function:

function array_multisort(&$a, array $column_names) {
    usort($a, function($a, $b) use($column_names) {
        foreach ($column_names as $column_name => $order) {
            $result = ($a[$column_name] <=> $b[$column_name]) * ($order === SORT_DESC ? -1 : 1);
            if ($result) return $result;
        }
        return 0;
    });
}


$data[] = array('volume' => 67, 'edition' => 2);
$data[] = array('volume' => 86, 'edition' => 1);
$data[] = array('volume' => 85, 'edition' => 6);
$data[] = array('volume' => 98, 'edition' => 2);
$data[] = array('volume' => 86, 'edition' => 6);
$data[] = array('volume' => 67, 'edition' => 7);


var_dump($data);
array_multisort($data, ['volume' => SORT_ASC, 'edition' => SORT_DESC]);
var_dump($data);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM