根据键对数组进行排序?

时间:2022-09-25 08:53:53

Is it possible in PHP to do something like this? How would you go about writing a function? Here is an example. The order is the most important thing.

在PHP中有可能做这样的事情吗?你要怎么写一个函数呢?这是一个例子。顺序是最重要的。

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

And I'd like to do something like

我想做一些类似的事情

$properOrderedArray = sortArrayByArray($customer, array('name', 'dob', 'address'));

Because at the end I use a foreach() and they're not in the right order (because I append the values to a string which needs to be in the correct order and I don't know in advance all of the array keys/values).

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

I've looked through PHP's internal array functions but it seems you can only sort alphabetically or numerically.

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

15 个解决方案

#1


272  

Just use array_merge or array_replace. Array_merge works by starting with the array you give it (in the proper order) and overwriting/adding the keys with data from your actual array:

只需使用array_merge或array_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')

ps - I'm answering this 'stale' question, because I think all the loops given as previous answers are overkill.

我在回答这个“陈腐”的问题,因为我认为之前给出的所有循环都是多余的。

#2


93  

There you go:

那就这样吧:

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;
}

#3


33  

Another way for PHP >= 5.3.0:

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);

Result:

结果:

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

Works fine with string and numeric keys.

可以很好地使用字符串和数字键。

#4


24  

How about this solution

这个解决方案

$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));
});

#5


21  

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;
}

#6


13  

Take one array as your order:

取一个数组作为您的顺序:

$order = array('north', 'east', 'south', 'west');

You can sort another array based on values using array_intersect­Docs:

你可以另一个数组基于值使用array_intersect­文档:

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

Or in your case, to sort by keys, use array_intersect_key­Docs:

或者在你的情况下,按键排序,使用array_intersect_key­文档:

/* sort by key: */
$array = array_flip($array);
$sorted = array_intersect_key(array_flip($order), $array);
print_r($sorted);

Both functions will keep the order of the first parameter and will only return the values (or keys) from the second array.

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

So for these two standard cases you don't need to write a function on your own to perform the sorting/re-arranging.

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

#7


2  

IF you have array in your array, you'll have to adapt the function by Eran a little bit...

如果你的数组中有数组,你将不得不稍微调整一下Eran的函数……

function sortArrayByArray($array,$orderArray) {
    $ordered = array();
    foreach($orderArray as $key => $value) {
        if(array_key_exists($key,$array)) {
                $ordered[$key] = $array[$key];
                unset($array[$key]);
        }
    }
    return $ordered + $array;
}

#8


1  

This function return a sub and sorted array based in second parameter $keys

该函数根据第二个参数$keys返回子数组和排序数组

function array_sub_sort(array $values, array $keys){
    $keys = array_flip($keys);
    return array_merge(array_intersect_key($keys, $values), array_intersect_key($values, $keys));
}

Example:

例子:

$array_complete = [
    'a' => 1,
    'c' => 3,
    'd' => 4,
    'e' => 5,
    'b' => 2
];

$array_sub_sorted = array_sub_sort($array_complete, ['a', 'b', 'c']);//return ['a' => 1, 'b' => 2, 'c' => 3];

#9


1  

I used the Darkwaltz4's solution but used array_fill_keys instead of array_flip, to fill with NULL if a key is not set in $array.

我使用了Darkwaltz4的解决方案,但是使用了array_fill_keys而不是array_flip来填充NULL(如果$array中没有设置键)。

$properOrderedArray = array_replace(array_fill_keys($keys, null), $array);

#10


0  

PHP has functions to help you with this:

PHP有一些函数可以帮助您:

$arrayToBeSorted = array('west', 'east', 'south', 'north');
$order = array('north', 'south', 'east', 'west');

// sort array
usort($arrayToBeSorted, function($a, $b) use ($order){
    // sort using the numeric index of the second array
    $valA = array_search($a, $order);
    $valB = array_search($b, $order);

    // move items that don't match to end
    if ($valA === false)
        return -1;
    if ($valB === false)
        return 0;

    if ($valA > $valB)
        return 1;
    if ($valA < $valB)
        return -1;
    return 0;
});

Usort does all the work for you and array_search provides the keys. array_search() returns false when it can't find a match so items that are not in the sort array naturally move to the bottom of the array.

Usort为你做所有工作,array_search提供密钥。array_search()在找不到匹配项时返回false,因此不在排序数组中的项自然会移动到数组的底部。

Note: uasort() will order the array without affecting the key => value relationships.

注意:uasort()将对数组进行排序,不影响键=>值关系。

#11


0  

  • sort as requested
  • 按要求排序
  • save for int-keys (because of array_replace)
  • 保存为int-keys(因为array_replace)
  • don't return keys are not existing in inputArray
  • 不要返回键在inputArray中不存在。
  • (optionally) filter keys no existing in given keyList
  • (可选)过滤给定密钥列表中不存在的密钥

Code:

代码:

 /**
 * sort keys like in key list
 * filter: remove keys are not listed in keyList
 * ['c'=>'red', 'd'=>'2016-12-29'] = sortAndFilterKeys(['d'=>'2016-12-29', 'c'=>'red', 'a'=>3 ]], ['c', 'd', 'z']){
 *
 * @param array $inputArray
 * @param string[]|int[] $keyList
 * @param bool $removeUnknownKeys
 * @return array
 */
static public function sortAndFilterKeys($inputArray, $keyList, $removeUnknownKeys=true){
    $keysAsKeys = array_flip($keyList);
    $result = array_replace($keysAsKeys, $inputArray); // result = sorted keys + values from input + 
    $result = array_intersect_key($result, $inputArray); // remove keys are not existing in inputArray 
    if( $removeUnknownKeys ){
        $result = array_intersect_key($result, $keysAsKeys); // remove keys are not existing in keyList 
    }
    return $result;
}

#12


0  

First Suggestion

第一个建议

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

Second Suggestion

第二个建议

$properOrderedArray = array_merge(array_flip(array('name', 'dob', 'address')), $customer);

I wanted to point out that both of these suggestions are awesome. However, they are apples and oranges. The difference? One is non-associative friendly and the other is associative friendly. If you are using 2 fully associative arrays then the array merge/flip will actually merge and overwrite the other associative array. In my case that is not the results I was looking for. I used a settings.ini file to create my sort order array. The data array I was sorting did not need to written over by my associative sorting counterpart. Thus array merge would destroy my data array. Both are great methods, both need to be archived in any developers toolbox. Based on your needs you may find you actually need both concepts in your archives.

我想指出的是,这两个建议都非常棒。然而,它们是苹果和桔子。区别呢?一种是非联想友好型,另一种是联想友好型。如果使用两个完全关联数组,那么数组merge/flip实际上会合并并覆盖另一个关联数组。在我看来,这不是我想要的结果。我使用一个设置。创建排序顺序数组的ini文件。我正在排序的数据数组不需要由我的关联排序对等物写入。因此数组合并会破坏数据数组。两者都是很好的方法,都需要在任何开发人员工具箱中存档。根据您的需要,您可能会发现您实际上需要您的存档中的这两个概念。

#13


0  

I adopted the answer from @Darkwaltz4 for its brevity and would like to share how I adapted the solution to situations where the array may contain different keys for each iteration like so:

我采用了@Darkwaltz4的答案,因为它简洁明了,我想分享一下我是如何将这个解决方案应用到这样的情况下的,在这种情况下,数组可能包含每个迭代的不同密钥,比如:

Array[0] ...
['dob'] = '12/08/1986';
['some_key'] = 'some value';

Array[1] ...
['dob'] = '12/08/1986';

Array[2] ...
['dob'] = '12/08/1986';
['some_key'] = 'some other value';

and maintained a "master key" like so:

并保持“主键”

$master_key = array( 'dob' => ' ' ,  'some_key' => ' ' );

array_merge would have executed the merge in the Array[1] iteration based on $master_key and produced ['some_key'] = '', an empty value, for that iteration. Hence, array_intersect_key was used to modify $master_key in each iterations like so:

array_merge将在基于$master_key的数组[1]迭代中执行合并,并生成['some_key'] = ",一个空值,用于该迭代。因此,在每次迭代中使用array_intersect_key修改$master_key,如下所示:

foreach ($customer as $customer) {
  $modified_key = array_intersect_key($master_key, $unordered_array);
  $properOrderedArray = array_merge($modified_key, $customer);
}

#14


0  

Without magic...

没有魔法……

$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;
}

#15


-1  

A bit late, but I couldn't find the way I implemented it, this version needs closure, php>=5.3, but could be altered not to:

有点晚了,但是我找不到实现的方式,这个版本需要闭包,php>=5.3,但是可以改成:

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

$order = array('name', 'dob', 'address');

$keys= array_flip($order);
uksort($customer, function($a, $b)use($keys){
    return $keys[$a] - $keys[$b];
});
print_r($customer);

Of course 'dontSortMe' needs to be sorted out, and may appear first in the example

当然,需要对“dontSortMe”进行排序,并可能首先出现在示例中

#1


272  

Just use array_merge or array_replace. Array_merge works by starting with the array you give it (in the proper order) and overwriting/adding the keys with data from your actual array:

只需使用array_merge或array_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')

ps - I'm answering this 'stale' question, because I think all the loops given as previous answers are overkill.

我在回答这个“陈腐”的问题,因为我认为之前给出的所有循环都是多余的。

#2


93  

There you go:

那就这样吧:

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;
}

#3


33  

Another way for PHP >= 5.3.0:

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);

Result:

结果:

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

Works fine with string and numeric keys.

可以很好地使用字符串和数字键。

#4


24  

How about this solution

这个解决方案

$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));
});

#5


21  

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;
}

#6


13  

Take one array as your order:

取一个数组作为您的顺序:

$order = array('north', 'east', 'south', 'west');

You can sort another array based on values using array_intersect­Docs:

你可以另一个数组基于值使用array_intersect­文档:

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

Or in your case, to sort by keys, use array_intersect_key­Docs:

或者在你的情况下,按键排序,使用array_intersect_key­文档:

/* sort by key: */
$array = array_flip($array);
$sorted = array_intersect_key(array_flip($order), $array);
print_r($sorted);

Both functions will keep the order of the first parameter and will only return the values (or keys) from the second array.

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

So for these two standard cases you don't need to write a function on your own to perform the sorting/re-arranging.

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

#7


2  

IF you have array in your array, you'll have to adapt the function by Eran a little bit...

如果你的数组中有数组,你将不得不稍微调整一下Eran的函数……

function sortArrayByArray($array,$orderArray) {
    $ordered = array();
    foreach($orderArray as $key => $value) {
        if(array_key_exists($key,$array)) {
                $ordered[$key] = $array[$key];
                unset($array[$key]);
        }
    }
    return $ordered + $array;
}

#8


1  

This function return a sub and sorted array based in second parameter $keys

该函数根据第二个参数$keys返回子数组和排序数组

function array_sub_sort(array $values, array $keys){
    $keys = array_flip($keys);
    return array_merge(array_intersect_key($keys, $values), array_intersect_key($values, $keys));
}

Example:

例子:

$array_complete = [
    'a' => 1,
    'c' => 3,
    'd' => 4,
    'e' => 5,
    'b' => 2
];

$array_sub_sorted = array_sub_sort($array_complete, ['a', 'b', 'c']);//return ['a' => 1, 'b' => 2, 'c' => 3];

#9


1  

I used the Darkwaltz4's solution but used array_fill_keys instead of array_flip, to fill with NULL if a key is not set in $array.

我使用了Darkwaltz4的解决方案,但是使用了array_fill_keys而不是array_flip来填充NULL(如果$array中没有设置键)。

$properOrderedArray = array_replace(array_fill_keys($keys, null), $array);

#10


0  

PHP has functions to help you with this:

PHP有一些函数可以帮助您:

$arrayToBeSorted = array('west', 'east', 'south', 'north');
$order = array('north', 'south', 'east', 'west');

// sort array
usort($arrayToBeSorted, function($a, $b) use ($order){
    // sort using the numeric index of the second array
    $valA = array_search($a, $order);
    $valB = array_search($b, $order);

    // move items that don't match to end
    if ($valA === false)
        return -1;
    if ($valB === false)
        return 0;

    if ($valA > $valB)
        return 1;
    if ($valA < $valB)
        return -1;
    return 0;
});

Usort does all the work for you and array_search provides the keys. array_search() returns false when it can't find a match so items that are not in the sort array naturally move to the bottom of the array.

Usort为你做所有工作,array_search提供密钥。array_search()在找不到匹配项时返回false,因此不在排序数组中的项自然会移动到数组的底部。

Note: uasort() will order the array without affecting the key => value relationships.

注意:uasort()将对数组进行排序,不影响键=>值关系。

#11


0  

  • sort as requested
  • 按要求排序
  • save for int-keys (because of array_replace)
  • 保存为int-keys(因为array_replace)
  • don't return keys are not existing in inputArray
  • 不要返回键在inputArray中不存在。
  • (optionally) filter keys no existing in given keyList
  • (可选)过滤给定密钥列表中不存在的密钥

Code:

代码:

 /**
 * sort keys like in key list
 * filter: remove keys are not listed in keyList
 * ['c'=>'red', 'd'=>'2016-12-29'] = sortAndFilterKeys(['d'=>'2016-12-29', 'c'=>'red', 'a'=>3 ]], ['c', 'd', 'z']){
 *
 * @param array $inputArray
 * @param string[]|int[] $keyList
 * @param bool $removeUnknownKeys
 * @return array
 */
static public function sortAndFilterKeys($inputArray, $keyList, $removeUnknownKeys=true){
    $keysAsKeys = array_flip($keyList);
    $result = array_replace($keysAsKeys, $inputArray); // result = sorted keys + values from input + 
    $result = array_intersect_key($result, $inputArray); // remove keys are not existing in inputArray 
    if( $removeUnknownKeys ){
        $result = array_intersect_key($result, $keysAsKeys); // remove keys are not existing in keyList 
    }
    return $result;
}

#12


0  

First Suggestion

第一个建议

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

Second Suggestion

第二个建议

$properOrderedArray = array_merge(array_flip(array('name', 'dob', 'address')), $customer);

I wanted to point out that both of these suggestions are awesome. However, they are apples and oranges. The difference? One is non-associative friendly and the other is associative friendly. If you are using 2 fully associative arrays then the array merge/flip will actually merge and overwrite the other associative array. In my case that is not the results I was looking for. I used a settings.ini file to create my sort order array. The data array I was sorting did not need to written over by my associative sorting counterpart. Thus array merge would destroy my data array. Both are great methods, both need to be archived in any developers toolbox. Based on your needs you may find you actually need both concepts in your archives.

我想指出的是,这两个建议都非常棒。然而,它们是苹果和桔子。区别呢?一种是非联想友好型,另一种是联想友好型。如果使用两个完全关联数组,那么数组merge/flip实际上会合并并覆盖另一个关联数组。在我看来,这不是我想要的结果。我使用一个设置。创建排序顺序数组的ini文件。我正在排序的数据数组不需要由我的关联排序对等物写入。因此数组合并会破坏数据数组。两者都是很好的方法,都需要在任何开发人员工具箱中存档。根据您的需要,您可能会发现您实际上需要您的存档中的这两个概念。

#13


0  

I adopted the answer from @Darkwaltz4 for its brevity and would like to share how I adapted the solution to situations where the array may contain different keys for each iteration like so:

我采用了@Darkwaltz4的答案,因为它简洁明了,我想分享一下我是如何将这个解决方案应用到这样的情况下的,在这种情况下,数组可能包含每个迭代的不同密钥,比如:

Array[0] ...
['dob'] = '12/08/1986';
['some_key'] = 'some value';

Array[1] ...
['dob'] = '12/08/1986';

Array[2] ...
['dob'] = '12/08/1986';
['some_key'] = 'some other value';

and maintained a "master key" like so:

并保持“主键”

$master_key = array( 'dob' => ' ' ,  'some_key' => ' ' );

array_merge would have executed the merge in the Array[1] iteration based on $master_key and produced ['some_key'] = '', an empty value, for that iteration. Hence, array_intersect_key was used to modify $master_key in each iterations like so:

array_merge将在基于$master_key的数组[1]迭代中执行合并,并生成['some_key'] = ",一个空值,用于该迭代。因此,在每次迭代中使用array_intersect_key修改$master_key,如下所示:

foreach ($customer as $customer) {
  $modified_key = array_intersect_key($master_key, $unordered_array);
  $properOrderedArray = array_merge($modified_key, $customer);
}

#14


0  

Without magic...

没有魔法……

$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;
}

#15


-1  

A bit late, but I couldn't find the way I implemented it, this version needs closure, php>=5.3, but could be altered not to:

有点晚了,但是我找不到实现的方式,这个版本需要闭包,php>=5.3,但是可以改成:

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

$order = array('name', 'dob', 'address');

$keys= array_flip($order);
uksort($customer, function($a, $b)use($keys){
    return $keys[$a] - $keys[$b];
});
print_r($customer);

Of course 'dontSortMe' needs to be sorted out, and may appear first in the example

当然,需要对“dontSortMe”进行排序,并可能首先出现在示例中