简体   繁体   English

如何在PHP中使用usort()按数组中的两个值对字段进行排序,然后按ASC对字段进行排序?

[英]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 . 此处使用的键是01 ,您的键就像genderlast_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: 代码中的主要问题:

  • You split by \\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()应用于所有值。
  • The 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'
  • You might also want to skip empty lines in your input. 您可能还想跳过输入中的空行。
  • You do your sorting in a loop on your array, that is wrong. 您在数组上循环执行排序,这是错误的。 That outer loop should be removed. 该外部循环应被删除。 If you need it for listing the data, then move the sorting out of it. 如果您需要它来列出数据,则将其移出。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM