Jump to content

sort array by group


moagrius

Recommended Posts

hi,

 

i'm trying to sort an array of associative arrays, based on one of the keys.

 

if the value of the key is a primitive, normal sorting occurs - this works fine.

 

if the value of the key is an array, i'd like to have it sorted by "groups"

 

here's an example:

 

<?php

$data[] = array('name' => 'h', 'list' => array(1,2));
$data[] = array('name' => 'g', 'list' => array(1));
$data[] = array('name' => 'a', 'list' => array(1,3));
$data[] = array('name' => 'f', 'list' => array(2));
$data[] = array('name' => 'e', 'list' => array(2,3));
$data[] = array('name' => 'b', 'list' => array(3));
$data[] = array('name' => 'c', 'list' => array(1,2,3,4));
$data[] = array('name' => 'd', 'list' => array(3,4));

function deep_sort($array, $sorton){

usort($array, function($a, $b) use($sorton) {

	$a = $a[$sorton];
	$b = $b[$sorton];

	if(is_array($a) && is_array($b)){

		// this bit is obviously flawed - only included for illustrative purposes
		$a = implode('', $a);
		$b = implode('', $b);

	}

	return ($a == $b) ? 0 : ($a > $b) ? 1 : -1;

});

return $array;

}

$sorted_by_name = deep_sort($data, 'name');

print '<pre>';

print_r($sorted_by_name);

print '</pre>';

$sorted_by_list = deep_sort($data, 'list');

print '<pre>';

print_r($sorted_by_list);

print '</pre>';

?>

 

the sorted_by_name bit is fine - but for sorted_by_list, what i want returned is all the array ordered as follows:

 

all those with "1" (or the lowest if none have "1") in it's list value first, then all those remaining that have the next highest ("2"), etc.

 

so right now, the returns for sort_by_list look like this:

 

Array
(
    [0] => Array
        (
            [name] => g
            [list] => Array
                (
                    [0] => 1
                )

        )

    [1] => Array
        (
            [name] => f
            [list] => Array
                (
                    [0] => 2
                )

        )

    [2] => Array
        (
            [name] => b
            [list] => Array
                (
                    [0] => 3
                )

        )

    [3] => Array
        (
            [name] => h
            [list] => Array
                (
                    [0] => 1
                    [1] => 2
                )

        )

    [4] => Array
        (
            [name] => a
            [list] => Array
                (
                    [0] => 1
                    [1] => 3
                )

        )

    [5] => Array
        (
            [name] => e
            [list] => Array
                (
                    [0] => 2
                    [1] => 3
                )

        )

    [6] => Array
        (
            [name] => d
            [list] => Array
                (
                    [0] => 3
                    [1] => 4
                )

        )

    [7] => Array
        (
            [name] => c
            [list] => Array
                (
                    [0] => 1
                    [1] => 2
                    [2] => 3
                    [3] => 4
                )

        )

)

whereas i'd like to get back:

Array
(
    [0] => Array
        (
            [name] => g
            [list] => Array
                (
                    [0] => 1
                )

        )

    [1] => Array
        (
            [name] => h
            [list] => Array
                (
                    [0] => 1
                    [1] => 2
                )

        )

    [2] => Array
        (
            [name] => c
            [list] => Array
                (
                    [0] => 1
                    [1] => 2
                    [2] => 3
                    [3] => 4
                )

        )

    [3] => Array
        (
            [name] => a
            [list] => Array
                (
                    [0] => 1
                    [1] => 3
                )

        )

    [4] => Array
        (
            [name] => f
            [list] => Array
                (
                    [0] => 2
                )

        )

    [5] => Array
        (
            [name] => e
            [list] => Array
                (
                    [0] => 2
                    [1] => 3
                )

        )

    [6] => Array
        (
            [name] => b
            [list] => Array
                (
                    [0] => 3
                )

        )   

    [7] => Array
        (
            [name] => d
            [list] => Array
                (
                    [0] => 3
                    [1] => 4
                )

        )

)

 

TYIA for any suggestions

Link to comment
Share on other sites

I couldn't get your code to run - getting an error about defining the function as a parameter for some reason. But, I was able to get the logic needed. Basically you need to test the min()'s of the two arrays. If the mins are not equal then sort the lowest min first. If they are equal you need to remove those min values and test the new mins. This process continues until you get unequal mins or until one or both arrays run out of values.

 

If you get two different mins the array with the lowest min gets sorted first. If one array runs out of values it is sorted first. If both arrays run out of values (they had the exact same values) return 0;

 

Here is the function I used. I'll leave it to you to determine how to implement the logic into your existing code:

function  sort_by_array ($a, $b)
{
    $a = $a['list']; $b = $b['list'];
    
    //Continue to remove the min value from each array until
    //they are not equal or until one runs out of values
    while(count($a)>0 && count($b)>0 && min($a)==min($b))
    {
        unset($a[array_search(min($a), $a)]);
        unset($b[array_search(min($b), $b)]);
    }
    //$a and $b have different min values
    if(count($a)>0 && count($b)>0)
    {
        return (min($a)>min($b))?1:-1;
    }
    //One or both arrays ran out of values
    return (count($a)!=count($b)) ? (count($a)==0)?-1:1 : 0;
}

Link to comment
Share on other sites

awesome - tested against a randomly populated dataset with 5000 items and much larger versions of "list" and it still holds up.  i've got this question on several boards and mailing lists and while we've come close with about 9 different approaches, yours appears complete and bullet-proof.  thank you!

Link to comment
Share on other sites

Yeah, some of the most difficult things to do with programming are ones that are "obvious" to a human. The trick is to walk throuh the problem and break it down into specific steps  - before you write the first line of code.

 

Please mark the topic as solved.

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.