Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I hope anyone can help me to fix a little problem. After getting a clear mind I still stuck and can't find a solution. I guess it is something obviously simple.

I stuck to an array structure and need to sort them. Here is a small example of the array:

$brand["BRAND_1"]["name"] = 'Brand Name 1';
$brand["BRAND_1"]["list"]['SUB_BRAND_1']['name'] = 'Headline Subbrand 1';
$brand["BRAND_1"]["list"]['SUB_BRAND_1']['text'] = 'text for Subbrand 1';
$brand["BRAND_1"]["list"]['SUB_BRAND_2']['name'] = 'Headline Subbrand 2';
$brand["BRAND_1"]["list"]['SUB_BRAND_2']['text'] = 'text for Subbrand 2';

$brand["BRAND_2"]["name"] = 'Brand Name 2';
$brand["BRAND_2"]["list"]['SUB_BRAND_1']['name'] = 'Headline Subbrand 1';
$brand["BRAND_2"]["list"]['SUB_BRAND_1']['text'] = 'text for Subbrand 1';

There could be n amount of BRAND_N and n amount of SUB_BRAND_N.

I have an order ID which stucks to a flexible order:

0 = out as in (dont worry about this, catch it at an earlier stage)
1 = BRAND_1.SUB_BRAND_1
2 = BRAND_1.SUB_BRAND_2
3 = BRAND_2.SUB_BRAND_1

This gets extended if there are more as these four cases and the order itself could change. So I have to work with the IDs.

The order should change the position in the array and push the value of the Id to the top in the array, for example:

order id = 2:

$brand["BRAND_1"]["name"] = 'Brand Name 1';
$brand["BRAND_1"]["list"]['SUB_BRAND_2']['name'] = 'Headline Subbrand 2';
$brand["BRAND_1"]["list"]['SUB_BRAND_2']['text'] = 'text for Subbrand 2';
$brand["BRAND_1"]["list"]['SUB_BRAND_1']['name'] = 'Headline Subbrand 1';
$brand["BRAND_1"]["list"]['SUB_BRAND_1']['text'] = 'text for Subbrand 1';

$brand["BRAND_2"]["name"] = 'Brand Name 2';
$brand["BRAND_2"]["list"]['SUB_BRAND_1']['name'] = 'Headline Subbrand 1';
$brand["BRAND_2"]["list"]['SUB_BRAND_1']['text'] = 'text for Subbrand 1';

order id = 3:

$brand["BRAND_2"]["name"] = 'Brand Name 2';
$brand["BRAND_2"]["list"]['SUB_BRAND_1']['name'] = 'Headline Subbrand 1';
$brand["BRAND_2"]["list"]['SUB_BRAND_1']['text'] = 'text for Subbrand 1';

$brand["BRAND_1"]["name"] = 'Brand Name 1';
$brand["BRAND_1"]["list"]['SUB_BRAND_1']['name'] = 'Headline Subbrand 1';
$brand["BRAND_1"]["list"]['SUB_BRAND_1']['text'] = 'text for Subbrand 1';
$brand["BRAND_1"]["list"]['SUB_BRAND_2']['name'] = 'Headline Subbrand 2';
$brand["BRAND_1"]["list"]['SUB_BRAND_2']['text'] = 'text for Subbrand 2';

I have tried this so far:

<?php

$order[1] = 'BRAND_1::SUB_BRAND_1';
$order[2] = 'BRAND_1::SUB_BRAND_2';
$order[3] = 'BRAND_2::SUB_BRAND_1';

// for testing
$orderId = 2;

// get the brand and sub_brand
$part = explode("::", $order[$orderId]); 

// set the new brand list
$newBrand[$part[0]]['name'] = $brand[$part[0]]['name'];
$newBrand[$part[0]]['list'][$part[1]] = $brand[$part[0]]['list'][$part[1]];

// unset the brand which should be first of the main brand array
unset($brand[$part[0]]['list'][$part[1]]);

// if there was only one list unset the whole brand part
if( count($brand[$part[0]]['list']) < 1 ) {
    unset( $brand[$part[0]] );
}

Now I have two arrays:

$brand includes the whole brands except this one which should be the first

$newBrand includes only this brand which should be at the top

Now I just need to add $brand to $newBrand but there is my problem :) Tried a lot of different ways from rebuilding the array to push the content, replace or merge... but I always run in circles.

Any other idea, shorter code, better approach..?

I wrote the whole code into codepad.org for better testing: Codepad example

Any help or suggestion appreciated.

Cheers!

EDIT:

Sorry for the misunderstanding:

The order is a specification outside the code. The aim is to set one element depending on the orderId to the top in the $brand array. The $orderId will get passed by POST, GET or a class call.

The $order array is just an array which helps me to make the specification accessible in the code.

So the $orderId match one element of the $order array and will return this element which should be on the top of the $brand array. Due to the fact that there is no numeric keys I decide to use the "brand::sub_brand" syntax to access on both depth level.

Hope this explains it a litte better.

Thanks

share|improve this question
    
Order ID determines only the first element, other elements will be ordered as specified in order IDs array, right? –  galymzhan Sep 30 '11 at 3:59
    
Can you clarify: You HAVE to use the array structure from the beginning? Are you saying that the sort can change? If so, where are you getting your sort instructions? –  Shad Sep 30 '11 at 4:00
    
*update and hope this answers your questions –  Talisin Sep 30 '11 at 4:14
add comment

1 Answer

up vote 1 down vote accepted

Here is one possible solution (test it here):

<?php

function getOrderingRules()
{
    return array(
        1 => 'BRAND_1.SUB_BRAND_1',
        2 => 'BRAND_1.SUB_BRAND_2',
        3 => 'BRAND_2.SUB_BRAND_1',
    );
}

function getOrderedBrands($brands, $orderId)
{
    $rules = getOrderingRules();
    if (!isset($rules[$orderId])) {
        throw new RuntimeException("Rule for order id '$orderId' is not specified");
    }

    $result = array();

    // Push the first element
    list($key, $subkey) = explode('.', $rules[$orderId]);
    $result[$key] = array(
        'name' => $brands[$key]['name'],
        'list' => array(
            $subkey => $brands[$key]['list'][$subkey],
        ),
    );

    // Push remaining elements in the order they appear in $rules
    foreach ($rules as $oid => $rule) {
        // Skip order id of the first element
        if ($oid == $orderId) {
            continue;
        }
        list($key, $subkey) = explode('.', $rules[$oid]);
        if (!isset($result[$key])) {
            $result[$key] = array(
                'name' => $brands[$key]['name'],
                'list' => array(),
            );
        }
        $result[$key]['list'][$subkey] = $brands[$key]['list'][$subkey];
    }

    return $result;
}

// Loading all brands (could be external source, like database)
$brand["BRAND_1"]["name"] = 'Brand Name 1';
$brand["BRAND_1"]["list"]['SUB_BRAND_1']['name'] = 'Headline Subbrand 1';
$brand["BRAND_1"]["list"]['SUB_BRAND_1']['text'] = 'text for Subbrand 1';
$brand["BRAND_1"]["list"]['SUB_BRAND_2']['name'] = 'Headline Subbrand 2';
$brand["BRAND_1"]["list"]['SUB_BRAND_2']['text'] = 'text for Subbrand 2';

$brand["BRAND_2"]["name"] = 'Brand Name 2';
$brand["BRAND_2"]["list"]['SUB_BRAND_1']['name'] = 'Headline Subbrand 1';
$brand["BRAND_2"]["list"]['SUB_BRAND_1']['text'] = 'text for Subbrand 1';

// Sort and output
print_r(getOrderedBrands($brand, 1));
print_r(getOrderedBrands($brand, 2));
print_r(getOrderedBrands($brand, 3));

You should be aware that with this array structure ($brands) you won't be able to set ordering rules like this:

1 = BRAND_1.SUB_BRAND_1
2 = BRAND_2.SUB_BRAND_1
3 = BRAND_1.SUB_BRAND_2

because once you met element keyed by BRAND_1, you have to iterate over all of it's sub-brands. If you don't have such rules, everything is fine. Otherwise you have to store sorted array structured like this (because actually you are sorting sub-brands, not brands):

$subBrands = array(
    array(
        'name' => 'Headline Subbrand 1',
        'text' => 'Text for it',
        'parent' => 'BRAND_1',
        'key' => 'SUB_BRAND_1',
    ),
    array(
        'name' => 'Headline Subbrand 2',
        'text' => 'Text for it',
        'parent' => 'BRAND_1',
        'key' => 'SUB_BRAND_2',
    ),
);
$parentBrands = array(
    'BRAND_1' => 'Brand Name 1',
    'BRAND_2' => 'Brand Name 2',
);

Then you can sort $subBrands and iterate over it

share|improve this answer
    
Thats awesome. There wont be a rule to mix up the sub_brands. So your solution works perfect. And I also figured out where my failure was. Thanks dude! –  Talisin Sep 30 '11 at 5:05
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.