基于另一个数组按键对数组进行排序?

ale*_*lex 136 php arrays sorting

在PHP中可以做这样的事情吗?你会如何写一个函数?这是一个例子.订单是最重要的.

$customer['address'] = '123 fake st';
$customer['name'] = 'Tim';
$customer['dob'] = '12/08/1986';
$customer['dontSortMe'] = 'this value doesnt need to be sorted';
Run Code Online (Sandbox Code Playgroud)

我想做点什么

$properOrderedArray = sortArrayByArray($customer, array('name', 'dob', 'address'));
Run Code Online (Sandbox Code Playgroud)

因为最后我使用foreach()并且它们的顺序不正确(因为我将值附加到需要按正确顺序排列的字符串中,并且我事先并不知道所有数组键/值).

我查看了PHP的内部数组函数,但似乎只能按字母顺序或数字顺序排序.

小智 323

只需使用array_mergearray_replace.Array_merge通过从你给它的数组(以正确的顺序)开始并覆盖/添加来自实际数组的数据的键来工作:

$customer['address'] = '123 fake st';
$customer['name'] = 'Tim';
$customer['dob'] = '12/08/1986';
$customer['dontSortMe'] = 'this value doesnt need to be sorted';

$properOrderedArray = array_merge(array_flip(array('name', 'dob', 'address')), $customer);
//Or:
$properOrderedArray = array_replace(array_flip(array('name', 'dob', 'address')), $customer);

//$properOrderedArray -> array('name' => 'Tim', 'address' => '123 fake st', 'dob' => '12/08/1986', 'dontSortMe' => 'this value doesnt need to be sorted')
Run Code Online (Sandbox Code Playgroud)

ps - 我正在回答这个"陈旧"的问题,因为我认为所有作为先前答案给出的循环都是过度的.

  • 如果您有字符串键但它不适用于数字键,它可以很好地工作.PHP文件:"如果输入的数组中有相同的字符串键,则该键的后面的值将覆盖前一个.然而,如果数组包含数字键,后面的值将不会覆盖原来的值,而是会.追加". (28认同)
  • 很好,但如果键中不存在键怎么办?我需要这个,但只有当任何键存在时...可能需要一个foreach然后... (6认同)
  • 对于我的情况,它是array_replace而不是array_merge.array_merge将两个值组合在一起,而不是将第二个数组替换为有序键. (5认同)
  • 另外,如果'order'数组(即数组('name','dob','address'))具有比要排序的数组更多的键,那么带有原始数组的结果排序数组的附加array_intersect将被切断在array_merge添加的杂散键. (4认同)
  • 几年前,我在寻找不同的东西时偶然发现了你的解决方案 - 而且我认为,与循环相比,这是非常有效的.现在我需要你的解决方案,我花了一个小时的时间来寻找它!谢谢! (3认同)

Era*_*rin 99

你去:

function sortArrayByArray(array $array, array $orderArray) {
    $ordered = array();
    foreach ($orderArray as $key) {
        if (array_key_exists($key, $array)) {
            $ordered[$key] = $array[$key];
            unset($array[$key]);
        }
    }
    return $ordered + $array;
}
Run Code Online (Sandbox Code Playgroud)

  • 那么你可以用+符号加入2个数组吗?我从来不知道,我一直在使用`array_merge()`! (12认同)
  • 一旦找到值,你应该插入一个`break`语句. (5认同)
  • 这比使用`usort()`还是`uasort()`更好? (3认同)
  • @alex用数组`+`运算符替换`array_merge()`时要非常小心.它通过键(也用于数字键)和*从左到右*合并,而`array_merge`从*从右到左合并*并且永远不会覆盖数字键.例如`[0,1,2] + [0,5,6,7] = [0,1,2,7]`而`array_merge([0,1,2],[0,5,6,7 ])= [0,1,2,0,5,6,7]`和`['a'=> 5] + ['a'=> 7] = ['a'=> 5]`但是` array_merge(['a'=> 5],['a'=> 7])= ['a'=> 7]`. (3认同)
  • `foreach($ orderArray as $ key => $ v)`为我做了诀窍 (2认同)

Pet*_*oot 41

这个解决方案怎么样?

$order = array(1,5,2,4,3,6);

$array = array(
    1 => 'one',
    2 => 'two',
    3 => 'three',
    4 => 'four',
    5 => 'five',
    6 => 'six'
);

uksort($array, function($key1, $key2) use ($order) {
    return (array_search($key1, $order) > array_search($key2, $order));
});
Run Code Online (Sandbox Code Playgroud)

  • 这不是很有效。对于每次比较,都会在数组中执行两次线性搜索。如果我们假设 uksort() 的时间复杂度为“O(n * log n)”,那么该算法的运行时间为“O(n^2 * log(n))”。 (4认同)

eku*_*ser 36

PHP的另一种方式> = 5.3.0:

$customer['address'] = '123 fake st';
$customer['name'] = 'Tim';
$customer['dob'] = '12/08/1986';
$customer['dontSortMe'] = 'this value doesnt need to be sorted';

$customerSorted = array_replace(array_flip(array('name', 'dob', 'address')), $customer);
Run Code Online (Sandbox Code Playgroud)

结果:

Array (
  [name] => Tim
  [dob] => 12/08/1986
  [address] => 123 fake st
  [dontSortMe] => this value doesnt need to be sorted
)
Run Code Online (Sandbox Code Playgroud)

使用字符串和数字键可以正常工作.

  • +当它们都起作用时,我发现“ array_replace()”比“ array_merge()”更好地传达了意图。 (2认同)

OIS*_*OIS 23

function sortArrayByArray(array $toSort, array $sortByValuesAsKeys)
{
    $commonKeysInOrder = array_intersect_key(array_flip($sortByValuesAsKeys), $toSort);
    $commonKeysWithValue = array_intersect_key($toSort, $commonKeysInOrder);
    $sorted = array_merge($commonKeysInOrder, $commonKeysWithValue);
    return $sorted;
}
Run Code Online (Sandbox Code Playgroud)


hak*_*kre 14

将一个数组作为您的订单:

$order = array('north', 'east', 'south', 'west');
Run Code Online (Sandbox Code Playgroud)

您可以使用array_intersectDocs基于值对另一个数组进行排序:

/* sort by value: */
$array = array('south', 'west', 'north');
$sorted = array_intersect($order, $array);
print_r($sorted);
Run Code Online (Sandbox Code Playgroud)

或者在您的情况下,要按键排序,请使用array_intersect_key文档:

/* sort by key: */
$array = array_flip($array);
$sorted = array_intersect_key(array_flip($order), $array);
print_r($sorted);
Run Code Online (Sandbox Code Playgroud)

这两个函数将保持第一个参数的顺序,并且只返回第二个数组中的值(或键).

因此,对于这两种标准情况,您不需要自己编写函数来执行排序/重新排列.


小智 8

我用Darkwaltz4的解决方案,但使用array_fill_keys的替代array_flip,以填补NULL如果钥匙没有设置$array

$properOrderedArray = array_replace(array_fill_keys($keys, null), $array);
Run Code Online (Sandbox Code Playgroud)


小智 5

没有魔法...

$array=array(28=>c,4=>b,5=>a);
$seq=array(5,4,28);    
SortByKeyList($array,$seq) result: array(5=>a,4=>b,28=>c);

function sortByKeyList($array,$seq){
    $ret=array();
    if(empty($array) || empty($seq)) return false;
    foreach($seq as $key){$ret[$key]=$dataset[$key];}
    return $ret;
}
Run Code Online (Sandbox Code Playgroud)

  • 这很好用,谢谢,只需更新 `$dataset` 以匹配参数名称 (3认同)