php - Merge array-of-array with specifics similar values -
imagine have array:
$users = []; $users[0] = [ "name" => "john doe", "age" => 48, "email" => "john.doe@server-a.com", "points" => 5 ]; $users[1] = [ "name" => "john brother", "age" => 32, "email" => "john.brother@server-a.com", "points" => 8 ]; $users[2] = [ "name" => "john doe", "age" => 48, "email" => "john.doe@server-b.com", "points" => 3 ]; $users[3] = [ "name" => "john doe", "age" => 49, "email" => "john.doe@server-b.com", "points" => 7 ];
in code, need merge users when (same name + same age) or (same email), sum points , return unique copy of user, considering newer information of user, if merged.
so, note that:
user#0
can mergeuser#2
, because share (same name + same age);- but
user#0
can't merge directlyuser#3
, because of don't have similarity; user#2
can mergeuser#3
, because share (same email);- so, indirectly,
user#0
can mergeuser#3
,user#2
;
the result expected is:
$users[] = [ "name" => "john brother", "age" => 32, "email" => "john.brother@server-a.com", "points" => 8 ]; $users[] = [ "name" => "john doe", "age" => 49, "email" => "john.doe@server-b.com", "points" => 15 ];
note: user#id
, after merge, doesn't matter.
i'm not sure if there more efficient or elegant approach can try this:
$result = []; $tmp = []; array_walk($users, function ($value) use (&$result, &$tmp) { $hash = md5($value['name'].$value['age']); $sum = $value['points']; $e = $value['email']; if (array_key_exists($hash, $result)) { $sum += $result[$hash]['points']; } elseif (array_key_exists($e, $tmp)) { $hash = md5($tmp[$e]['name'].$tmp[$e]['age']); $sum += $result[$hash]['points']; } $result[$hash] = $tmp[$e] = $value; $result[$hash]['points'] = $sum; }); $users = array_values($result); var_dump($users);
the output is:
array (size=2) 0 => array (size=4) 'name' => string 'john doe' (length=8) 'age' => int 49 'email' => string 'john.doe@server-b.com' (length=21) 'points' => int 15 1 => array (size=4) 'name' => string 'john brother' (length=12) 'age' => int 32 'email' => string 'john.brother@server-a.com' (length=25) 'points' => int 8
Comments
Post a Comment