[英]How to sort by two values then a field by ASC in an array using usort() in PHP?
I have parsed three different text files: 我已经解析了三个不同的文本文件:
space.txt space.txt
Kournikova Anna F F 6-3-1975 Red
Hingis Martina M F 4-2-1979 Green
Seles Monica H F 12-2-197
comma.txt comma.txt
Abercrombie, Neil, Male, Tan, 2/13/1943
Bishop, Timothy, Male, Yellow, 4/23/1967
Kelly, Sue, Female, Pink, 7/12/1959
pipe.txt pipe.txt
Smith | Steve | D | M | Red | 3-3-1985
Bonk | Radek | S | M | Green | 6-3-1975
Bouillon | Francis | G | M | Blue | 6-3-1975
I used the following code to parse all files into one array ............. 我使用以下代码将所有文件解析为一个数组.............
<?php
$space_txt = './data/input/space.txt';
$comma_txt = './data/input/comma.txt';
$pipe_txt = './data/input/pipe.txt';
$parsed_space_data = file_get_contents($space_txt);
$parsed_comma_data = file_get_contents($comma_txt);
$parsed_pipe_data = file_get_contents($pipe_txt);
$space_array = myExpldeLoopFunc("space"," ", $parsed_space_data);
$comma_array = myExpldeLoopFunc("comma",",", $parsed_comma_data);
$pipe_array = myExpldeLoopFunc("pipe"," | ", $parsed_pipe_data);
$finalArray = array_merge($space_array, $comma_array, $pipe_array);
function changeGender($gender) {
if($gender === 'F') {
return str_replace('F', 'Female', $gender);
}
elseif($gender === 'M') {
return str_replace('M', 'Male', $gender);
}
}
function normalizeDate($date) {
return str_replace('-', '/', $date);
}
function myExpldeLoopFunc($name, $sep, $data) {
$parsedData = explode("\r", $data);
$arr = [];
foreach ($parsedData as $data) {
$data_arr = explode($sep, $data);
if($name == 'space'){
$arr[] = [
"last_name" => $data_arr[0],
"first_name" => $data_arr[1],
// "middle_initial" => $data_arr[2],
"gender" => changeGender($data_arr[3]),
"date_of_birth" => normalizeDate($data_arr[4]),
"favorite_color" => $data_arr[5]
];
}
elseif($name == 'comma') {
$arr[] = [
"last_name" => $data_arr[0],
"first_name" => $data_arr[1],
"gender" => $data_arr[2],
"date_of_birth" => normalizeDate($data_arr[4]),
"favorite_color" => $data_arr[3]
];
}
elseif ($name == 'pipe') {
$arr[] = [
"last_name" => $data_arr[0],
"first_name" => $data_arr[1],
// "middle_initial" => $data_arr[2],
"gender" => changeGender($data_arr[3]),
"date_of_birth" => normalizeDate($data_arr[5]),
"favorite_color" => $data_arr[4]
];
}
}
return $arr;
}
for ($i=0; $i < count($finalArray); $i++) {
foreach ($finalArray as $key => $row) {
$gender[$key] = $row['gender'];
$last_name[$key] = $row['last_name'];
}
array_multisort($gender, SORT_ASC, $last_name, SORT_ASC, $finalArray);
echo join(' ', $finalArray[$i]) . '<br>';
}
var_dump($finalArray);
?>
Now I have the following array ........... 现在我有以下数组........
array (size=9)
0 =>
array (size=5)
'last_name' => string 'Kournikova' (length=10)
'first_name' => string 'Anna' (length=4)
'gender' => string 'Female' (length=6)
'date_of_birth' => string '6/3/1975' (length=8)
'favorite_color' => string 'Red' (length=3)
1 =>
array (size=5)
'last_name' => string '
Hingis' (length=7)
'first_name' => string 'Martina' (length=7)
'gender' => string 'Female' (length=6)
'date_of_birth' => string '4/2/1979' (length=8)
'favorite_color' => string 'Green' (length=5)
2 =>
array (size=5)
'last_name' => string '
Seles' (length=6)
'first_name' => string 'Monica' (length=6)
'gender' => string 'Female' (length=6)
'date_of_birth' => string '12/2/1973' (length=9)
'favorite_color' => string 'Black' (length=5)
3 =>
array (size=5)
'last_name' => string 'Abercrombie' (length=11)
'first_name' => string ' Neil' (length=5)
'gender' => string ' Male' (length=5)
'date_of_birth' => string ' 2/13/1943' (length=10)
'favorite_color' => string ' Tan' (length=4)
4 =>
array (size=5)
'last_name' => string '
Bishop' (length=7)
'first_name' => string ' Timothy' (length=8)
'gender' => string ' Male' (length=5)
'date_of_birth' => string ' 4/23/1967' (length=10)
'favorite_color' => string ' Yellow' (length=7)
5 =>
array (size=5)
'last_name' => string '
Kelly' (length=6)
'first_name' => string ' Sue' (length=4)
'gender' => string ' Female' (length=7)
'date_of_birth' => string ' 7/12/1959' (length=10)
'favorite_color' => string ' Pink' (length=5)
6 =>
array (size=5)
'last_name' => string 'Smith' (length=5)
'first_name' => string 'Steve' (length=5)
'gender' => string 'Male' (length=4)
'date_of_birth' => string '3/3/1985' (length=8)
'favorite_color' => string 'Red' (length=3)
7 =>
array (size=5)
'last_name' => string '
Bonk' (length=5)
'first_name' => string 'Radek' (length=5)
'gender' => string 'Male' (length=4)
'date_of_birth' => string '6/3/1975' (length=8)
'favorite_color' => string 'Green' (length=5)
8 =>
array (size=5)
'last_name' => string '
Bouillon' (length=9)
'first_name' => string 'Francis' (length=7)
'gender' => string 'Male' (length=4)
'date_of_birth' => string '6/3/1975' (length=8)
'favorite_color' => string '
Blue' (length=4)
So Far the output is ........ 到目前为止,输出是........
Kelly Sue Female 7/12/1959 Pink
Bishop Timothy Male 4/23/1967 Yellow
Abercrombie Neil Male 2/13/1943 Tan
Hingis Martina Female 4/2/1979 Green
Seles Monica Female 12/2/1973 Black
Kournikova Anna Female 6/3/1975 Red
Bonk Radek Male 6/3/1975 Green
Bouillon Francis Male 6/3/1975 Blue
Smith Steve Male 3/3/1985 Red
I want to sort the array by Females then Males, then by last_name asc ........ 我想按女性,然后按男性,然后按last_name asc ........对数组进行排序
Hingis Martina Female 4/2/1979 Green
Kelly Sue Female 7/12/1959 Pink
Kournikova Anna Female 6/3/1975 Red
Seles Monica Female 12/2/1973 Black
Abercrombie Neil Male 2/13/1943 Tan
Bishop Timothy Male 4/23/1967 Yellow
Bonk Radek Male 6/3/1975 Green
Bouillon Francis Male 6/3/1975 Blue
Smith Steve Male 3/3/1985 Red
I also tried ...... 我也尝试过......
function sortBy($field, &$array, $direction = 'asc') {
usort($array, create_function('
$a, $b', ' $a = $a["' . $field . '"];
$b = $b["' . $field . '"];
if ($a == $b) {
return 0;
}
return ($a ' . ($direction == 'desc' ? '>' : '<') .' $b) ? -1 : 1; '));
return true;
}
for ($i=0; $i < count($finalArray); $i++) {
sortBy('gender', $finalArray);
sortBy('last_name', $finalArray);
echo join(' ', $finalArray[$i]) . '<br>';
}
I have tried array_multisort(), usort(), sort(), asort(), and I still couldn't produce the results I wanted. 我已经尝试过array_multisort(),usort(),sort(),asort(),但仍然无法产生想要的结果。 What solution can be used to produce the outcome?
可以使用什么解决方案来产生结果?
Ok, I'll give an example, with two criteria, but it's untested on your data. 好的,我举一个带有两个条件的示例,但这未经您的数据测试。 So the
compare()
function below receives two arrays to compare. 因此,下面的
compare()
函数接收两个要比较的数组。 How to do that? 怎么做? Each array, in the example, contains two numbers, first we sort on the number with key = 0 and then on the number with key = 1. Your keys are, of course, different.
在示例中,每个数组包含两个数字,首先我们对键= 0的数字进行排序,然后对键= 1的数字进行排序。当然,您的键是不同的。
function compare($array1,$array2)
{
// numbers at key 0 are equal
if ($array1[0] == $array2[0])
{
// so we look at key 1.
if ($array1[1] == $array2[1]) return 0;
return ($array1[1] < $array2[1]) ? -1 : 1;
}
return ($array1[0] < $array2[0]) ? -1 : 1;
}
$a = [[1,2],[3,4],[5,4],[4,2],[1,8]];
usort($a,'compare');
foreach ($a as $key => $value)
{
echo "<pre>$key: ".print_r($value,TRUE)."\n</pre>";
}
All you need to do is to adapt this to your case. 您需要做的就是使它适应您的情况。
This sorts on two values in an array, both, as you would call it, ascending. 这将对数组中的两个值进行升序排序,就像您将其称为升序一样。 Just change the
<
to >
if you want one of them in decending order. 如果您希望其中之一以降序排列,只需将
<
更改为>
。 The keys used here are 0
and 1
, your keys are like gender
and last_name
. 此处使用的键是
0
和1
,您的键就像gender
和last_name
。
Some values cannot be compared with the <
comparison operator, so you would need to use something else. 某些值无法与
<
比较运算符进行比较,因此您需要使用其他值。 In case of the last_name
you might want to use strcasecmp()
. 如果使用
last_name
,则可能要使用strcasecmp()
。
The main issues in your code: 代码中的主要问题:
\\r
: it is better to split by \\n
which works on all platforms. \\r
分割:最好用\\n
分割,这适用于所有平台。 But since a line-feed can be \\r\\n
, you need to remove that other character as well. \\r\\n
,所以您也需要删除该其他字符。 This you can do with trim()
. trim()
。 So I would suggest to apply trim()
to all values. trim()
应用于所有值。 changeGender
function looks weird. changeGender
函数看起来很奇怪。 You can do all that with: return $gender === 'F' ? 'Female' : 'Male'
return $gender === 'F' ? 'Female' : 'Male'
return $gender === 'F' ? 'Female' : 'Male'
. return $gender === 'F' ? 'Female' : 'Male'
。 The corrected code (and also nicely indented) follows with my comments marked as //**
: 经过更正的代码(也很好地缩进了),后面跟着我的注释标记为
//**
:
$space_txt = './data/input/space.txt';
$comma_txt = './data/input/comma.txt';
$pipe_txt = './data/input/pipe.txt';
$parsed_space_data = file_get_contents($space_txt);
$parsed_comma_data = file_get_contents($comma_txt);
$parsed_pipe_data = file_get_contents($pipe_txt);
$space_array = myExpldeLoopFunc("space", " ", $parsed_space_data);
$comma_array = myExpldeLoopFunc("comma", ",", $parsed_comma_data);
$pipe_array = myExpldeLoopFunc("pipe", " | ", $parsed_pipe_data);
$finalArray = array_merge($space_array, $comma_array, $pipe_array);
function changeGender($gender) {
return $gender === 'F' ? 'Female' : 'Male'; //** This is more straightforward
}
function normalizeDate($date) {
return str_replace('-', '/', $date);
}
function myExpldeLoopFunc($name, $sep, $data) {
$parsedData = explode("\n", $data); //** use "\n" instead of "\r"
$arr = [];
foreach ($parsedData as $data) {
if ($data === "") continue; //** skip empty lines
$data_arr = explode($sep, $data);
if($name == 'space'){
$arr[] = [
"last_name" => trim($data_arr[0]), //** trim all elements (also removes "\r")
"first_name" => trim($data_arr[1]),
// "middle_initial" => trim($data_arr[2]),
"gender" => changeGender(trim($data_arr[3])),
"date_of_birth" => normalizeDate(trim($data_arr[4])),
"favorite_color" => trim($data_arr[5])
];
} elseif($name == 'comma') {
$arr[] = [
"last_name" => trim($data_arr[0]),
"first_name" => trim($data_arr[1]),
"gender" => trim($data_arr[2]),
"date_of_birth" => normalizeDate(trim($data_arr[4])),
"favorite_color" => trim($data_arr[3])
];
} elseif ($name == 'pipe') {
$arr[] = [
"last_name" => trim($data_arr[0]),
"first_name" => trim($data_arr[1]),
// "middle_initial" => trim($data_arr[2]),
"gender" => changeGender(trim($data_arr[3])),
"date_of_birth" => normalizeDate(trim($data_arr[5])),
"favorite_color" => trim($data_arr[4])
];
}
}
return $arr;
}
//** Removed the bad for-loop that appeared here.
foreach ($finalArray as $key => $row) {
$gender[$key] = $row['gender'];
$last_name[$key] = $row['last_name'];
}
array_multisort($gender, SORT_ASC, $last_name, SORT_ASC, $finalArray);
//** Output in a loop, but leave the above sorting out of it
foreach ($finalArray as $row) {
echo join(' ', $row) . "<br>\n";
}
print_r($finalArray);
See it run on eval.in which uses the sample data you provided. 看到它在eval.in上运行,它使用您提供的示例数据。
The order is as desired. 顺序是所需的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.