dopa53272
dopa53272
2017-03-03 06:27
浏览 43
已采纳

基于多个键从多维数组中删除重复项

Sorry if this was asked before, but I searched a lot and couldn't find a solution. I've been trying to solve this problem for a while now, and couldn't write the function for it.

I have an array like that:

    $numbers = array(
        array("tag" => "developer", "group" => "grp_1", "num" => "123123"),
        array("tag" => "developer", "group" => "grp_2", "num" => "111111"),
        array("tag" => "student", "group" => "grp_1", "num" => "123123"),
        array("tag" => "student", "group" => "grp_2", "num" => "123123"),
        array("tag" => "developer", "group" => "grp_3", "num" => "111111"),
    );

I need to write a function, that removes the duplicates off this array, based on multiple keys, so my function call should look something like that:

unique_by_keys($numbers, array("num","group"));

In other terms, one number can't be in the same group more than once.

After calling unique_by_keys() by array should be like that:

    $numbers = array(
        array("tag" => "developer", "group" => "grp_1", "num" => "123123"),
        array("tag" => "developer", "group" => "grp_2", "num" => "111111"),
        array("tag" => "student", "group" => "grp_2", "num" => "123123"),
        array("tag" => "developer", "group" => "grp_3", "num" => "111111"),
    );

I'd appreciate if you could help me find a solution, or lead me to the correct way of thinking. Thanks!


SOLUTION: I was able to find a solution, by writing the following function: ( I wrote it in a way that accepts many forms of $haystack arrays )

function unique_by_keys($haystack = array(), $needles = array()) {
    if (!empty($haystack) && !empty($needles)) {
        $_result = array();
        $result = array();
        $i = 0;
        foreach ($haystack as $arrayObj) {
            if (is_array($arrayObj)) {
                $searchArray = array();
                foreach ($needles as $needle) {
                    if (isset($arrayObj[$needle])) {
                        $searchArray[$needle] = $arrayObj[$needle];
                    }
                }
                if (!in_array($searchArray, $_result)) {
                    foreach ($arrayObj as $key => $value) {
                        if (in_array($key, $needles)) {
                            $_result[$i][$key] = $value;
                        }
                    }
                    $result[] = array_merge($_result[$i], $arrayObj);
                }
            } else {
                $result[] = $arrayObj;
            }
            $i++;
        }
        return $result;
    }
}

Thanks for everyone that replied!

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

3条回答 默认 最新

  • dongxili9934
    dongxili9934 2017-03-03 07:18
    已采纳

    Bhaskar's approach which assigns unique keys in the loop to remove duplicates affords a very small function for this case.

    Here is a previous and unnecessarily complicated version:

    function unique_by_keys($haystack=array(),$needles=array()){
        // reverse order of sub-arrays to preserve lower-indexed values
        foreach(array_reverse($haystack) as $row){
            $result[implode('',array_intersect_key($row,array_flip($needles)))]=$row; // assign unique keys
        }
        ksort($result);  // sort the sub-arrays by their assoc. keys
        return array_values($result); // replace assoc keys with indexed keys
    }
    

    This is the best/leanest solution I can come up with:

    $numbers = array(
            array("tag" => "developer", "group" => "grp_1", "num" => "123123"),
            array("tag" => "developer", "group" => "grp_2", "num" => "111111"),
            array("tag" => "student",   "group" => "grp_1", "num" => "123123"),
            array("tag" => "student",   "group" => "grp_2", "num" => "123123"),
            array("tag" => "developer", "group" => "grp_3", "num" => "111111")
        );
    
    function unique_by_keys($haystack=array(),$needles=array()){
        foreach($haystack as $row){
            $key=implode('',array_intersect_key($row,array_flip($needles)));  // declare unique key
            if(!isset($result[$key])){$result[$key]=$row;} // save row if non-duplicate
        }
        return array_values($result);
    }
    
    echo "<pre>";
    var_export(unique_by_keys($numbers,array("group","num")));
    echo "</pre>";
    

    Output:

    array (
      0 => 
      array (
        'tag' => 'developer',
        'group' => 'grp_1',
        'num' => '123123',
      ),
      1 => 
      array (
        'tag' => 'developer',
        'group' => 'grp_2',
        'num' => '111111',
      ),
      2 => 
      array (
        'tag' => 'student',
        'group' => 'grp_2',
        'num' => '123123',
      ),
      3 => 
      array (
        'tag' => 'developer',
        'group' => 'grp_3',
        'num' => '111111',
      ),
    )
    
    点赞 评论
  • dtlzdofl66441
    dtlzdofl66441 2017-03-03 06:46

    Code might not be efficient, but i will work for you :)

    $result = unique_by_keys($numbers, array("num","group"));
    
    echo "<pre>";
    print_R($result);
    
    function unique_by_keys($numbers, $arr){
        $new_array = array();
        $output = array();
        foreach ($numbers as $n){
    
            if(isset($new_array[$n[$arr[1]]]) && $new_array[$n[$arr[1]]] == $n[$arr[0]]){
                continue;
            }else{
                $new_array[$n[$arr[1]]] = $n[$arr[0]];
                $output[] = $n;
            }
    
        }
        return $output;
    }
    
    点赞 评论
  • dpz7935
    dpz7935 2017-03-03 06:51
    $newNumbers = array();
    foreach($numbers as $key=>$values){
        $newkey = $values['group'].'__'.$values['num']; 
        $newNumbers[$newkey] = $values;
    }
    var_dump($newNumbers)
    
    点赞 评论

相关推荐