0

I have a working delivery system that I need to present in alphabetical order sorted by the city, which is the key in a subarray.

This is the array:

array (
    'option_3' => array (
        'Rio' => '18',
    ),
    'option_4' => array (
        'Tokyo' => '20',
    ),
    'option_5' => array (
        'Berlim' => '23',
    )
)

And it is shown in this table:

<table>
    <tr>
        <th>ID</th>
        <th>Bairro</th>
        <th>Valor</th>
        <th>Ação</th>
    </tr>


[a foreach goes here]

    <tr>
        <td><?php echo $option_number;?></td>
        <td><?php echo $city;?></td>
        <td><?php echo $price;?></td>
        <td><button type='submit'>Remove</button></td>
    </tr>
<table>

This produces the folowing result:

ID  City  Value Action
3   Rio     18  Remover
4   Tokyo   20  Remover
5   Berlim  23  Remover

But I need it to be sorted by the city:

ID  City  Value Action
5   Berlim  23  Remover
3   Rio     18  Remover
4   Tokyo   20  Remover

How could I accomplish this?

2
  • usort Commented Sep 27, 2019 at 14:36
  • Firstly merge all option array and then sort the array. So you can use the array merge function and after that the you need to use the sort function. After that the result come that you want. Commented Sep 27, 2019 at 14:43

4 Answers 4

2

You need to preserve the outer keys, use uasort(). I prefer the spaceship (3-way comparison) operator between two key() calls.

Code: (Demo)

$options = [
    'option_3' => [
        'Rio' => '18',
    ],
    'option_4' => [
        'Tokyo' => '20',
    ],
    'option_5' => [
        'Berlim' => '23',
    ]
];

uasort($options, function ($a, $b) {
    return key($a) <=> key($b);
});
var_export($options);

Output:

array (
  'option_5' => 
  array (
    'Berlim' => '23',
  ),
  'option_3' => 
  array (
    'Rio' => '18',
  ),
  'option_4' => 
  array (
    'Tokyo' => '20',
  ),
)

From PHP7.4+, You can use arrow syntax inside custom functions. (Demo)

uasort($options, fn($a, $b) => key($a) <=> key($b));

Preparing for an array_multisort() call is prohibitively hideous, IMO. (Demo)

array_multisort(array_keys(array_merge(...array_values($options))), $options);
Sign up to request clarification or add additional context in comments.

1 Comment

I still think the PHP7.4+ version looks more like hieroglyphics though!
1

Firstly, create a single array for each city and push them into a new array like that:

$options = [
    'option_3' => [
        'Rio' => '18',
    ],
    'option_4' => [
        'Tokyo' => '20',
    ],
    'option_5' => [
        'Berlim' => '23',
    ]
];

$newOptions = [];

foreach($options as $key => $option) {
    array_push($newOptions, [
        'id' => $key,
        'city' => key($option),
        'price' => reset($option)
    ]);
}

After, just sort it alphabetically by the value of each 'city' using usort()

usort($newOptions, function($a, $b) {
    return strcmp($a['city'], $b['city']);
});

Finally, you can simply do a foreach into $newOptions and echo whatever you want based on keys 'id', 'city' and 'price'. Example:

foreach($newOptions as $option)

<tr>
    <td><?php echo $option['id'];?></td>
    <td><?php echo $option['city']?></td>
    <td><?php echo $option['price']?></td>
    <td><button type='submit'>Remove</button></td>
</tr>

Comments

0

Ok, this sort is little trickier as we need to preserve the parent key for each city as well. So, we go as follows:

  • Modify the current array to have an extra parent_key in it's subarray which would look like:

    'option_3' => array (
        'Rio' => '18',
        'parent_key' => 'option_3'
    )
    
  • Now, we use usort() to compare the 2 subarrays via name through strcmp() and return the result.

  • We again iterate through them and use array_keys() to iterate over the data set. We do this as we are going to restore the parent key back without running into concurrent modification issue while iterating over the same array.

Code:

<?php

$data = array (
            'option_3' => array (
                'Rio' => '18',
            ),
            'option_4' => array (
                'Tokyo' => '20',
            ),
            'option_5' => array (
                'Berlim' => '23',
            )
        );


foreach($data as $key => &$value){
    $value['parent_key'] = $key;
}


usort($data,function($val1,$val2){
    $name1 = array_keys($val1)[0];
    $name2 = array_keys($val2)[0];
    return strcmp($name1,$name2); 
});

foreach(array_keys($data) as $index){
    $value = $data[$index];
    $parent_key = $value['parent_key'];
    unset($value['parent_key']); // unset parent key now as it is no longer needed
    $data[$parent_key] = $value;
    unset($data[$index]); // unset numeric index modified by usort()
}


print_r($data);

Demo: https://3v4l.org/q0YFk

Update: Current result does not hold extra keys like city etc, but it is easy to figure that out as a city name while doing a foreach in key-value fashion.

Comments

0

You can accomplish that in many ways, here is my way Demo, hope it works for you.

$arr = array (
    'option_3' => array (
        'Rio' => '18',
    ),
    'option_4' => array (
        'Tokyo' => '20',
    ),
    'option_5' => array (
        'Berlim' => '23',
    )
);

$cities = [];

foreach($arr as $key=>$val){
    foreach($val as $key2=>$city){

        $option = explode('_', $key);
        $cities[$key2] = $city.'_'.$option[1];
    }
}
ksort($cities);

$res = [];
foreach($cities as $key=>$val){
    $temp = [];
    $temp['city'] = $key;
    $val_opt = explode('_', $val);
    $temp['value'] = $val_opt[0];
    $temp['option'] = $val_opt[1];

    $res[] = $temp;
}

print_r($res);

Output:

Array
(
    [0] => Array
        (
            [city] => Berlim
            [value] => 23
            [option] => 5
        )

    [1] => Array
        (
            [city] => Rio
            [value] => 18
            [option] => 3
        )

    [2] => Array
        (
            [city] => Tokyo
            [value] => 20
            [option] => 4
        )

)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.