1

I have a following array and i need to sort this array based upon the key value. I wrote a code and got perfect result if all numeric keys are different.

$myarray_need_to_sort =Array
(
    [13] => 214
    [14] => 215
    [15] => 216
    [21] => 223
)

Here is my code

$order = array();
foreach ($myarray_need_to_sort as $value){
    $cat = Mage::getModel('catalog/category')->load($value);
    $order[$cat->getTabOrder()] = $value;
}   
ksort($order);
$sorted_order = array();
foreach ($order as $key=>$value)
{
    $sorted_order[$key] = $value;
}

print_r($sorted_order);

$cat->getTabOrder() is the sort order i am getting from backend and result is perfect

Array
(
    [1] => 216
    [2] => 223
    [3] => 215
    [4] => 214
)

The code is sorting array perfectly but the issue is that if same key exists ie someone added $cat->getTabOrder() same say 2 and 2 for two values then it is removing one key. I need to add one increment for this like

Array
(
    [1] => 216
    [2] => 223
    [2] => 215 -- it should be 3 and 4 should be 5 but it is removing 2 from here
    [4] => 214 -- should be 5
)
RD Mage
  • 103
  • 3
  • 16
  • You can use array_key_exists php function to check if the key already exists befor inserting it into the array and if it does you can change the key. – Indrajit Mar 14 '16 at 07:50
  • Why should `4` be changed to `5` in your example? And what if `3` already exists when the second `2` appears? Or if three (or more) of `2` appears? You are looking for a solution to something that is not your problem but a candidate solution for it. It's an [XY problem](http://xyproblem.info). You better forget about increment and try to explain what you want to achive. Keeping all values, even when the keys conflict is one of the goals. Sorting by key is another goal. What about the sorting of the values associated to duplicate keys? An example would be great. – axiac Mar 14 '16 at 11:00
  • @axiac basically i am creating tabs like accessories, softwares, others, warranty and admin set their sort order by mistake from back-end with an attribute. I just want to show those on frontend with sorting order as admin defined but i can't able to achieve when admin entered duplicate sort order by mistake say 2 for 2 tabs and 1 and 3 for other. – RD Mage Mar 14 '16 at 11:10

1 Answers1

0

As I said in a comment, this looks like an XY problem. You don't actually need to increment the keys, you need to keep all the values (including when the keys are duplicate) and sort them by key.

I'll assume when two or more items have the same key, the order they come from the database must be kept in the final list.

The goals are:

  • keep all the values;
  • sort them by keys;
  • when two or more items have the same key, keep the order they arrived.

Having this in mind, a possible solution is to keep in $order, for each key the list of items that have that key. Sort the list by keys then either iterate over the array using two nested foreach loops or flatten it before using it.

The code:

// $order[$key] is the list of $cat items having $cat->getTabOrder() == $key
$order = array();
foreach ($myarray_need_to_sort as $value){
    $cat = Mage::getModel('catalog/category')->load($value);
    $key = $cat->getTabOrder();
    if (! array_key_exists($key, $order)) {
        // This is the first $cat having $key as tab order
        // Create a new list of $key
        $order[$key] = array();
    }
    // Add $value to the list of is $key (tab order)
    $order[$key][] = $value;
}
// Sort the outer array by keys
ksort($order);

A print_r($order) should display something like:

Array
(
    [1] => Array
        (
            [0] => 216
        )
    [2] => Array
        (
            [0] => 223
            [1] => 215
        )
    [4] => Array
        (
            [0] => 214
        )
)

Now, you can retrieve the values from the array by iterating over each sub-array:

foreach ($order as $key => $list) {
    foreach ($list as $value) {
        echo('$key='.$key.': $value='.$value."\n");
    }
}

It displays:

$key=1: $value=216
$key=2: $value=223
$key=2: $value=215
$key=4: $value=214

If you don't care about the keys anymore and all you need is the list of $value after sorting then you can put the values into a new list in the double foreach above (instead of displaying them).

Or you can write it in a more compact way using array_reduce() and array_merge():

$new = array_reduce($order, 'array_merge', array());
print_r($new);

The output is:

Array
(
    [0] => 216
    [1] => 223
    [2] => 215
    [3] => 214
)

Notice that the original keys are lost, the new list is indexed sequentially.

axiac
  • 68,258
  • 9
  • 99
  • 134