检测数组中元素的移动位置


detect where elements in array moved

我必须能够检测"公会"(如活动提要)中的所有更改,包括新数据和旧数据。数据以这种方式呈现为数组:

{"GUILDMASTER":["foo"],"OFFICER":["bar","baz"],"MEMBER":["foobar","foobaz"]}

例如,我需要检测"bar"是否从当前排名下降一(到"MEMBER"),它将输出一个类似于以下的数组:

[{"user":"bar","was_found_in":"OFFICER","now_found_in":"MEMBER"}]

我目前拥有的,下面,只检测一个成员是否已经加入了left,有没有任何方法可以扩展它来实现我想要的?

function compareThem($a, $b) {
    $flat_new = call_user_func_array('array_merge', $a);
    $flat_old = call_user_func_array('array_merge', $b);
    $rm = array();
    if($flat_new != $flat_old) {
        $new_old = array_diff($flat_new, $flat_old);
        $old_new = array_diff($flat_old, $flat_new);
        $diff = array_merge($new_old, $old_new);
        foreach ($diff as $key => $value) {
            if(in_array($value, $flat_new) && !in_array($value, $flat_old)) {
                $rm[] = array("new"=>true, "left"=>false, "user"=>$value);
            } else if(in_array($value, $flat_old) && !in_array($value, $flat_new)) {
                $rm[] = array("new"=>false, "left"=>true, "user"=>$value);
            }
        }
    }
    return $rm;
}
$new = array("GUILDMASTER" => array("foo"), "OFFICER" => array("bar", "baz"), "MEMBER" => array("foobar", "foobaz"));
$old = array("GUILDMASTER" => array("foo"), "OFFICER" => array("bar", "baz"), "MEMBER" => array("foobar"));
compareThem($new,$old) // will output [{"new":true,"left":false,"user":"foobaz"}]

您可以这样做。它检测添加、删除和修改:

// your array before the change
$before = ["GUILDMASTER" => ["foo"], "OFFICER" => ["bar","baz"], "MEMBER" => ["foobar","foobaz"]];
// your array after the change (foo was moved from GUILDMASTER to OFFICER)
$after = ["GUILDMASTER" => [], "OFFICER" => ["bar","baz", "foo"], "MEMBER" => ["foobar","foobaz"]];
// create lookup table to check the position a person previously held
$positions_before = [];
foreach($before as $position => $people) {
  foreach($people as $person) {
    $positions_before[$person] = $position;
  }
}
// scan new positions...
$changes = [];
foreach($after as $position => $people) {
  foreach($people as $person) {
    // track when a new person is added (they wont be in the table)
    if(!isset($positions_before[$person])) {
      $changes[] = ["user" => $person, "was_found_in" => "DIDNT_EXIST", "now_found_in" => $position];
    // track when a change is detected (different value than table)
    }elseif($positions_before[$person] != $position) {
      $changes[] = ["user" => $person, "was_found_in" => $positions_before[$person], "now_found_in" => $position];
    }
    // remove this person from the table after parsing them
    unset($positions_before[$person]);
  }
}
// anyone left in the lookup table is in $before and $after
// so track that they were removed/fired
foreach($positions_before as $person => $position) {
  $changes[] = ["user" => $person, "was_found_in" => $position, "now_found_in" => "REMOVED"];
}
print_r($changes);

输出[user] => foo [was_found_in] => GUILDMASTER [now_found_in] => OFFICER