0

I’m almost going out of my mind – I hope you can help; maybe it’s simple but I’m really stuck right now.

I have the following unordered array of arrays:

$variations_excerpt =
Array ( [4288] => Array ( [pa_farbe] => white-default [pa_groesse] => xl ) 
         [128] => Array ( [pa_farbe] => black-default [pa_groesse] => s )
         [130] => Array ( [pa_farbe] => black-default [pa_groesse] => xxl )
        [4289] => Array ( [pa_farbe] => white-default [pa_groesse] => xxl )
         [127] => Array ( [pa_farbe] => black-default [pa_groesse] => m ) 
         [129] => Array ( [pa_farbe] => black-default [pa_groesse] => xl ) 
        [4286] => Array ( [pa_farbe] => [pa_groesse] => )
         [149] => Array ( [pa_farbe] => black-default [pa_groesse] => l )
        [4287] => Array ( [pa_farbe] => white-default [pa_groesse] => s )
         [126] => Array ( [pa_farbe] => black-default [pa_groesse] => l )
        [4290] => Array ( [pa_farbe] => white-default [pa_groesse] => ) )

(I don’t want to emphasize this, but note that there are empty values (='') sprinkled around in it. It’s meant to be that way.)

Another note: in some odd situations there is a chance that doublettes do exist. In this example one does exist:

...
[126] => Array ( [pa_farbe] => black-default [pa_groesse] => l )
...
[149] => Array ( [pa_farbe] => black-default [pa_groesse] => l ) 
...

I think it’s important to answer the 'doublette question' in advance. ;)

Now, this unordered array above needs to be sorted according to the following array, providing the desired order of all the values. I already managed to make this:

$unique_attribute_values = 
Array ( [pa_farbe] => Array ( [0] => black-default [1] => white-default [2] => ) 
      [pa_groesse] => Array ( [5] => s [6] => m [7] => l [8] => xl [9] => xxl [10] => ) ) 

(The empty values (='') are shifted towards the end.)

Additionally I already know, how many 'dimensions' such an array will have and what are the 'names' of them, the attributes:

$dim = 0;
$dim_names = array();
foreach ($unique_attribute_values as $attr => $val) {
    $dim++;
    $dim_names[$dim] = $attr; 
    }

… resulting in:

$dim = 2;
$dim_names = Array ( [1] => pa_farbe 
                     [2] => pa_groesse ) 

Please note: the 'dimensionality' in this example is 2 – but the dimensionality can vary from 1 to n (with n in praxis almost always < 4). But since it’s kind of unknown, I thought it’s a good idea to determine the dimensionality and have the names (=keys) available, maybe for a future for-loop. (?)

Anyway, the result I need to achieve is the following:

$ordered_excerpt = 
Array ( [128] => Array ( [pa_farbe] => black-default [pa_groesse] => s ) 
        [127] => Array ( [pa_farbe] => black-default [pa_groesse] => m )
        [126] => Array ( [pa_farbe] => black-default [pa_groesse] => l )
        [149] => Array ( [pa_farbe] => black-default [pa_groesse] => l )
        [129] => Array ( [pa_farbe] => black-default [pa_groesse] => xl ) 
        [130] => Array ( [pa_farbe] => black-default [pa_groesse] => xxl )
       [4287] => Array ( [pa_farbe] => white-default [pa_groesse] => s )
       [4288] => Array ( [pa_farbe] => white-default [pa_groesse] => xl ) 
       [4289] => Array ( [pa_farbe] => white-default [pa_groesse] => xxl ) 
       [4290] => Array ( [pa_farbe] => white-default [pa_groesse] => )
       [4286] => Array ( [pa_farbe] => [pa_groesse] => ) ) 

Note that the doublette is on its right place too: [126] and [149].

How would you do it? I appreciate any suggestions!

Thank you very much in advance!

1 Answer 1

1

You have 2 options here: Use uasort or uksort. If you use uasort, the issue you'll face is incase of duplicates. From your expected output, it seems that if the arrays are same, they should ordered by their keys. In uasort compare function you won't have access to those keys.

So you'll have to use uksort and use the key to index into the variations_excerpt array and compare the two values. The compare function is relatively simple as we have the distinct dimensions and the unique_attribute_values array.

Here's the code:

<?php
$variations_excerpt =
array ( 4288 => array ( 'pa_farbe' => 'white-default', 'pa_groesse' => 'xl' ) ,
         128 => array ( 'pa_farbe' => 'black-default', 'pa_groesse' => 's' ),
         130 => array ( 'pa_farbe' => 'black-default', 'pa_groesse' => 'xxl' ),
        4289 => array ( 'pa_farbe' => 'white-default', 'pa_groesse' => 'xxl' ),
         127 => array ( 'pa_farbe' => 'black-default', 'pa_groesse' => 'm' ) ,
         129 => array ( 'pa_farbe' => 'black-default', 'pa_groesse' => 'xl' ) ,
        4286 => array ( 'pa_farbe' => '',   'pa_groesse' => ''),
         149 => array ( 'pa_farbe' => 'black-default', 'pa_groesse' => 'l' ),
        4287 => array ( 'pa_farbe' => 'white-default', 'pa_groesse' => 's' ),
         126 => array ( 'pa_farbe' => 'black-default', 'pa_groesse' => 'l' ),
        4290 => array ( 'pa_farbe' => 'white-default', 'pa_groesse' => '' ) 
        );

$dummy = $variations_excerpt;

$unique_attribute_values = 
array ( 
    'pa_farbe' => array ( 
        0 => 'black-default', 
        1 => 'white-default', 
        2 => '' 
    ), 
     'pa_groesse' => array ( 
        5 => 's', 
        6 => 'm', 
        7 => 'l', 
        8 => 'xl', 
        9 => 'xxl', 
        10 => ''
      )
    );
$dim_names = array('pa_farbe', 'pa_groesse');
uksort($variations_excerpt, "cmp");

function cmp($a, $b) {
    global $dim_names, $unique_attribute_values, $dummy;
    foreach($dim_names as $d) {
        $x = array_search($dummy[$a][$d], $unique_attribute_values[$d]);
        $y = array_search($dummy[$b][$d], $unique_attribute_values[$d]);
        if ($x < $y) {
            return -1;
        } else if ($x > $y) {
            return 1;
        }
    }
    if ($a < $b)
        return -1;
    else
        return 1;
}

print_r($variations_excerpt);

?>

Hope it helps.

Note: Possible issues as pointed out by the OP:

(1) One needs to define the 'cmp' function before it is called in uksort(). Alternatively, one can make use of an anonymous function insinde of uksort().

(2) One needs to initialize the global variables used in 'cmp' function scope also outside of this scope als 'global' first.

Sign up to request clarification or add additional context in comments.

3 Comments

Dude, I think this is it! Awesome!
I just needed to make some minor alterations to your answer, maybe you can edit them in: (1) One needs to define the 'cmp' function before it is called in uksort(). Alternatively, one can make use of an anonymous function insinde of uksort() – like I did for now. (2) One needs to initialize the global variables used in 'cmp' function scope also outside of this scope als 'global' first. Then it works fine! (Maybe behavior is depending on php version?) (Oh, and: sorry for answering kind of late, but my graphics card decided to die the next morning after posting this question …)
It indeed looks like the issues you mentioned are dependent on specific versions or perhaps specific settings. It runs good here: ideone.com/dx9DlO

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.