3

I currently have an array of objects as shown below:

$aa = new StdClass;
$aa->name = 'aa';
$aa->index = 30;
$bb = new StdClass;
$bb->name = 'bb';
$bb->index = 30;
$cc = new StdClass;
$cc->name = 'cc';
$cc->index = 10;
$dd = new StdClass;
$dd->name = 'dd';
$dd->index = 20;
$ee = new StdClass;
$ee->name = 'ee';
$ee->index = 10;

I have placed my objects into an array for sorting:

$arr = [$aa, $bb, $cc, $dd];

I also have an additional array which I would like to be used for sorting the objects in order at the index e.g. $aa->index:

$map = [30, 20, 10, 10, 30];

An expected result would be:

[$aa, $dd, $cc, $ee, $bb]

The other of $aa and $bb is undefined, they must simply not repeat and all indices must be assigned somewhere.

What would be the best way to arrange $arr in order set by $map WITHOUT the use of a foreach() loop?

deceze
  • 510,633
  • 85
  • 743
  • 889
Coffee
  • 2,063
  • 8
  • 24
  • 57
  • How do you decide whether the first index - `30` - refers to the object `$aa` or `$bb`? – Jirka Hrazdil Dec 12 '16 at 10:44
  • @JiriHrazdil randomly, I suppose – Coffee Dec 12 '16 at 10:47
  • Given your example - is `[$aa, $dd, $cc, $cc, $aa]` a correct output? – Jirka Hrazdil Dec 12 '16 at 10:49
  • No, should be [$aa, $dd, $cc, $ee, $bb] or somehow like that. No repeats – Coffee Dec 12 '16 at 10:57
  • `$map` is always the same `[30, 20, 10, 10, 30]`? If not, How this order is defined? – James Dec 12 '16 at 11:42
  • http://stackoverflow.com/a/17364128/476 → *Sorting into a manual, static order* – deceze Dec 12 '16 at 12:39
  • 1
    This is not a duplicate, using array_search in this case won't work because the reference $order (or $map in this case) has duplicated values, all objects from original array with the same index property will be sorted one next to the other regardless the position in $order or $map. – phobia82 Dec 12 '16 at 12:56

2 Answers2

0

I'm honestly not sure if I understood the question right, but here's an attempt at your problem:

$aa = new stdClass;
$aa->name = 'aa';
$aa->index = 30;
$bb = new stdClass;
$bb->name = 'bb';
$bb->index = 30;
$cc = new stdClass;
$cc->name = 'cc';
$cc->index = 10;
$dd = new stdClass;
$dd->name = 'dd';
$dd->index = 20;
$ee = new stdClass;
$ee->name = 'ee';
$ee->index = 10;


$arr = [$aa, $bb, $dd, $cc,  $ee];
$map = [30, 30 , 10,  20];

function sort_ish($arr, $map)
{
    $return = [];

    while($element = array_shift($map))
    {
        foreach($arr as $key => $value)
        {
            if($element == $value->index)
            {
                $return[] = $value;
                unset($arr[$key]);
                break 1;
            }
        }
    }

    return $return;
}

print_r(sort_ish($arr, $map));

Which will output:

Array
(
    [0] => stdClass Object
(
    [name] => aa
[index] => 30
        )

    [1] => stdClass Object
(
    [name] => bb
[index] => 30
        )

    [2] => stdClass Object
(
    [name] => cc
[index] => 10
        )

    [3] => stdClass Object
(
    [name] => dd
[index] => 20
        )

)

Really, I had to use a foreach.

On a different note, I had a lot of fun with this question, even if I didn't get it right. Thanks OP.

Andrei
  • 3,434
  • 5
  • 21
  • 44
0

I've done this by technically not calling a foreach() loop, but I am looping using a recursive function. All you need to do do is pass the object array ($arr) as the first param and your array map ($mapArr) as your second to the function mrSorty(). mrSorty() will then take it from here passing your object array through magical functions such as array_search() and ksort().

$arr = [$aa, $bb, $cc, $dd, $ee];
$mapArr = [30, 20, 10, 10, 30];

function mrSorty($arr, $mapArr, $objCount=0) {

    static $newArr; 

      if ((count($mapArr)) > 0 && $objCount < ($objCount+count($mapArr)) ) {

            $obj = $arr[$objCount];
            $key = array_search($obj->index, $mapArr);
            $newArr[$key] = $obj;
            unset($mapArr[$key]);
            mrSorty($arr, $mapArr, ++$objCount);
      } 

      ksort($newArr); //Sort the Array by Key
      return $newArr; 
}



$arrayReturn = mrSorty($arr, $mapArr); //Array of Objects & Array Map

var_dump($arrayReturn);

Output

array(5) {
[0] => object(stdClass) #1 (2) { ["name"]= > string(2)"aa" ["index"] => int(30)}
[1] => object(stdClass) #4 (2) { ["name"]= > string(2) "dd" ["index"] => int(20)}
[2] => object(stdClass) #3 (2) { ["name"]= > string(2) "cc" ["index"] => int(10)}
[3] => object(stdClass) #5 (2) { ["name"]= > string(2) "ee" ["index"] => int(10)}
[4] => object(stdClass) #2 (2) { ["name"]= > string(2)"bb" ["index"] => int(30)}
}

Edit:

On a serious note, if you need to me elaborate then let me know.

Kitson88
  • 2,889
  • 5
  • 22
  • 37