Sort a multidimensional array by a column, keeping the same lines of the array

Asked

Viewed 7,700 times

4

I have an array with two columns, where in the first column I have the name of a station, and in the second I have the address of the same.

I need to sort this array alphabetically by station name, without losing the associated address!

I tried the function array_multisort(), but I can only sort the columns separately. You can help me?

This was the code used, based on the function documentation array_multisort(). It returns the "$data" vector still out of order, and the "$sites" and "$Ips" vectors are empty.

            $data = array( 'sites' => $lista_estacoes, 'IPs' => $lista_enderecos);

            foreach ($data as $key => $row) {
                    $sites[$key] = $row['sites'];
                    $IPs[$key] = $row['IPs'];
            }

            array_multisort($sites, SORT_DESC, $IPs, SORT_ASC, $data);

Where "$lista_estacoes" and "$lista_enderecos" are the vectors containing the data of the stations. Some error I am not noticing?

The array "$data" is like this:

 Array
 (
     [sites] => Array
         (
        [0] => 

        [1] => PrimeiraEstacao

        [2] => SegundaEstacao

        [3] => TerceiraEstacao

        [4] => 

        [5] => QuintaEstacao

...
         )

     [IPs] => Array
         (
        [0] => 

        [1] => 172.168.0.11

        [2] => 172.168.0.12

        [3] => 172.168.0.13

        [4] => 172.168.0.14

        [5] => 172.168.0.15

...
         )
 )
  • Face a glance at the documentation of the array_multisort I believe that Example #3 Sorting database Results is your case

  • @Adirkuhn, thank you! I edited the question by adding the code made based on the documentation, which does not yet do the ordering. Can you find a mistake?

  • shows how this is the contents of your array

  • @Does Adirkuhn have 730 lines, something specific in the composition of it? Analyzing it, I found some null values in the 'sites' column, this can interfere with the function?

  • Not in theory, but put a small piece of that array to see its structure

  • @Adirkuhn, edited with a piece of the array.

Show 1 more comment

4 answers

1

A possible solution is to group the values two by two before sorting:

$arr = array_map(null, $arr["sites"], $arr["IPs"]);

Sort according to zero index, referring to column sites:

usort($arr, function ($a, $b) {
    return strcmp($a[0], $b[0]);
});

After, return the list of values separating the pairs usingarray_column:

return [
    "sites" => array_column($arr, 0),
    "IPs"   => array_column($arr, 1)
];

That is, the function that makes the desired ordering would be:

function order ($arr)
{
    $arr = array_map(null, $arr["sites"], $arr["IPs"]);

    usort($arr, function ($a, $b) {
        return strcmp($a[0], $b[0]);
    });

    return [
        "sites" => array_column($arr, 0),
        "IPs"   => array_column($arr, 1)
    ];
}

For a test input equal to:

$data = Array(
    'sites' => Array(
        0 => '',
        1 => '5 Estacao',
        2 => '3 Estacao',
        3 => '4 Estacao',
        4 => '1 Estacao',
        5 => '2 Estacao',
    ),
    'IPs' => Array(
        0 => '',
        1 => '172.168.0.15',
        2 => '172.168.0.13',
        3 => '172.168.0.14',
        4 => '172.168.0.11',
        5 => '172.168.0.12',
    )
);

The output generated by print_r(order($data)) will be:

Array
(
    [sites] => Array
        (
            [0] => 
            [1] => 1 Estacao
            [2] => 2 Estacao
            [3] => 3 Estacao
            [4] => 4 Estacao
            [5] => 5 Estacao
        )

    [IPs] => Array
        (
            [0] => 
            [1] => 172.168.0.11
            [2] => 172.168.0.12
            [3] => 172.168.0.13
            [4] => 172.168.0.14
            [5] => 172.168.0.15
        )
)

Which is exactly the entry list, ordered by the name of the site, without losing the order of the Ips.

See working on Ideone.

0

$arrayTeste = Array(
    'sites' => Array(
        0 => '',
        1 => '5 Estacao',
        2 => '3 Estacao',
        3 => '4 Estacao',
        4 => '1 Estacao',
        5 => '2 Estacao',
    ),
    'IPs' => Array(
        0 => '',
        1 => '172.168.0.15',
        2 => '172.168.0.13',
        3 => '172.168.0.14',
        4 => '172.168.0.11',
        5 => '172.168.0.12',
    )
);

First I suggest unifying the data:

$newArray = array();
foreach ($arrayTeste['sites'] as $k => $value){
    $newArray[$k] = array(
        'name' => $value,
        'ip'   => $arrayTeste['IPs'][$k],
    );
}

After this function you perform Sort:

function arraySort($array, $on, $order=SORT_ASC){
    $new_array = array();
    $sortable_array = array();

    if (count($array) > 0) {
        foreach ($array as $k => $v) {
            if (is_array($v)) {
                foreach ($v as $k2 => $v2) {
                    if ($k2 == $on) {
                        $sortable_array[$k] = $v2;
                    }
                }
            } else {
                $sortable_array[$k] = $v;
            }
        }

        switch ($order) {
            case SORT_ASC:
                asort($sortable_array);
            break;
            case SORT_DESC:
                arsort($sortable_array);
            break;
        }

        foreach ($sortable_array as $k => $v) {
            $new_array[$k] = $array[$k];
        }
    }

    return $new_array;
}

$newArray = arraySort($newArray, 'name');

Out :

Array
(
    [0] => Array
        (
            [name] => 
            [ip] => 
        )

    [4] => Array
        (
            [name] => 1 Estacao
            [ip] => 172.168.0.11
        )

    [5] => Array
        (
            [name] => 2 Estacao
            [ip] => 172.168.0.12
        )

    [2] => Array
        (
            [name] => 3 Estacao
            [ip] => 172.168.0.13
        )

    [3] => Array
        (
            [name] => 4 Estacao
            [ip] => 172.168.0.14
        )

    [1] => Array
        (
            [name] => 5 Estacao
            [ip] => 172.168.0.15
        )

)

-1

Have you tried using the usort? Order before creating your $data.

function cmpSites($a, $b)
{
    return strcmp($a["sites"], $b["sites"]);
}

function cmpIPs($a, $b)
{
    return strcmp($a["IPs"], $b["IPs"]);
}

usort($lista_estacoes, "cmpSites");
usort($lista_enderecos, "cmpIps");

$data = array( 'sites' => $lista_estacoes, 'IPs' => $lista_enderecos);

Ideone example

  • Maicon, this code sorts the IP addresses separately, losing the station name corresponding to it. , so does not solve. I need the names to be sorted, but the corresponding IP addresses to follow them, so that both remain in the same position! That’s why I’m trying to put them in a multidimensional array.

-1

Try to use the method array_map():


$data = array(
         'sites' => $lista_estacoes,
         'IPs' => $lista_enderecos
         );

          $new_data = array_map($data['sites'], $data['IPs']);

usort($new_data);

print_r($new_data);


Browser other questions tagged

You are not signed in. Login or sign up in order to post.