1

I have the following array.

{
  "flow":[
    {
      "tasks":[
        { "id":"1", "uid":"bryan" },
        { "id":"2", "uid":"eric" }
      ]
    },
    {
      "tasks":[
        { "id":"1", "uid":"bryan" },
        { "id":"2", "uid":"eric" }
      ]
    },
    {
      "tasks":[
        { "id":"1", "uid":"bryan" },
        { "id":"2", "uid":"eric" }
      ]
    },
    {
      "tasks":[
        { "id":"1", "uid":"bryan" },
        { "id":"2", "uid":"eric" },
        { "id":"3", "uid":"eric" },
        { "id":"4", "uid":"bryan" }
      ]
    }
  ]
}

Let's say I am eric. If I am eric, I am trying to move all items with the uid of eric to the front of the tasks array.

So that the array would end looking like this:

{
  "flow":[
    {
      "tasks":[
        { "id":"2", "uid":"eric" },
        { "id":"1", "uid":"bryan" }
      ]
    },
    {
      "tasks":[
        { "id":"2", "uid":"eric" },
        { "id":"1", "uid":"bryan" }
      ]
    },
    {
      "tasks":[
        { "id":"2", "uid":"eric" },
        { "id":"1", "uid":"bryan" }
      ]
    },
    {
      "tasks":[
        { "id":"2", "uid":"eric" },
        { "id":"3", "uid":"eric" },
        { "id":"1", "uid":"bryan" },
        { "id":"4", "uid":"bryan" }
      ]
    }
  ]
}

I've attempted to make a function to do it, but for some reason it's not working the way I intended it to. Does anyone know what I'm doing wrong?

function reorder_flow($flow, $uid)
{   
    foreach($flow as &$step)
    {   
        //step is the array with tasks
        $tasks = $step['tasks'];
        $new_tasks = array();

        foreach($tasks as $key => $t)
        {
            if($t['uid'] == $uid)
            {
                $new_tasks = $new_tasks + $t;
                unset($tasks[$key]);
            }
        }
        $step['tasks'] = $new_tasks + $step['tasks'];
    }
    return $flow;
}
4
  • 2
    In what way is it not working the way you intended? You included what you expect the output to look like, but what does the actual output look like? Commented Jul 28, 2016 at 18:28
  • is this a php array? Commented Jul 28, 2016 at 18:31
  • 1
    It appears he is outputting it with json_encode @marmeladze Commented Jul 28, 2016 at 18:32
  • As an aside, assuming this is a php array, I'm not 100% sure if using + does what you want, so maybe look into array_merge Commented Jul 28, 2016 at 18:32

3 Answers 3

1

This is a traversal/sorting problem.

$json = <<<JSON
{
  "flow":[
    {
      "tasks":[
        { "id":"1", "uid":"bryan" },
        { "id":"2", "uid":"eric" }
      ]
    },
    {
      "tasks":[
        { "id":"1", "uid":"bryan" },
        { "id":"2", "uid":"eric" }
      ]
    },
    {
      "tasks":[
        { "id":"1", "uid":"bryan" },
        { "id":"2", "uid":"eric" }
      ]
    },
    {
      "tasks":[
        { "id":"1", "uid":"bryan" },
        { "id":"2", "uid":"eric" },
        { "id":"3", "uid":"eric" },
        { "id":"4", "uid":"bryan" }
      ]
    }
  ]
}
JSON;

$flow = json_decode($json, true);

array_walk($flow['flow'], function(&$flowItem, $key){
    usort($flowItem['tasks'], function($a, $b){
        $aIsMatch = $a['uid'] === 'eric';
        $bIsMatch = $b['uid'] === 'eric';
        if ($aIsMatch && $bIsMatch) {
            return 0;
        }
        if ($aIsMatch) {
            return -1;
        }
        if ($bIsMatch) {
            return 1;
        }
        // Fallback sorting criteria - you could use something else or just return 0
        return strcasecmp($a['uid'], $b['uid']);
    });
});


echo json_encode($flow, JSON_PRETTY_PRINT);
Sign up to request clarification or add additional context in comments.

Comments

1

Please try this:

function sortByUID(&$array, $uid) {

    array_walk ($array, function($obj) use($uid) {
        uasort($obj->tasks, function($a, $b) use($uid)  {
            return $a->uid == $uid ? -1 : 1;
        });
    }); 

}

sortByUID($data->flow, 'eric');

Demo: https://3v4l.org/mOhDX

I hope this will help.

4 Comments

More refined version of what I did - nicely done and I like that you put it in a function
Yes! only seconds between the 2 answers; We had the same idea ;)
I like that version too, fine refactored :)
My first editon was like that too, only the array_walk part was the old foreach :)
0

notes:

  • + does not work with arrays in that way

  • json_decode should have the second parameter set to true to get nested arrays

then try this in the foreach:

//step is the array with tasks
$new_tasks=array();
foreach($step['tasks'] as $t){
   if($t['uid'] == $uid){
      array_unshift($new_tasks,$t);
   } else {
      array_push($new_tasks,$t);
   }
}

$step['tasks'] = $new_tasks;

4 Comments

Your first answer you posted worked, why did you change it?
mmh it worked, ok, then take that, but i think it was not so safty at all. Test some combinations :)
I appreciate the help! I will try and decipher what's going on here and wrap my head around it :)
Late hint: with function () use (&$var) it is possible to inject variables into a function, so that they can used there.

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.