【问题标题】:combine 3 dimensional array into single array and remove duplicate values?将 3 维数组组合成单个数组并删除重复值?
【发布时间】:2018-05-02 05:08:11
【问题描述】:

我得到 3 维数组,在不同数组中有重复值,我想将这个 3 维数组组合成一个数组并删除最终数组中的重复值。

我的数组是:

Array
(
[0] => Array
    (
        [0] => Array
            (
                [role_id] => 2
                [name] => name1
                [email] => email1@somemail.com
            )

        [1] => Array
            (
                [role_id] => 2
                [name] => name2
                [email] => email2@somemail.com
            )

        [2] => Array
            (
                [role_id] => 2
                [name] => name3 
                [email] => email3@somemail.com
            )
    )

[1] => Array
    (
        [0] => Array
            (
                [role_id] => 2
                [name] => name4
                [email] => email4@somemail.com
            )

        [1] => Array
            (
                [role_id] => 2
                [name] => name3 
                [email] => email3@somemail.com
            )
    )

[2] => Array
    (
        [0] => Array
            (
                [role_id] => 2
                [name] => name3 
                [email] => email3@somemail.com
            )

        [1] => Array
            (
                [role_id] => 2
                [name] => name2
                [email] => email2@somemail.com
            )
    )
[3] => Array
    (
        [0] => Array
            (
                [role_id] => 2
                [name] => name3 
                [email] => email3@somemail.com
            )
    )
)

我尝试了以下解决方案,但没有奏效:

Solution-1: array_unique(array_merge($array1,$array2), SORT_REGULAR);
Solution-2: function array_flatten($array) { 
               if (!is_array($array)) { 
                 return FALSE; 
               } 
               $result = array(); 
               foreach ($array as $key => $value) { 
                 if (is_array($value)) { 
                   $result = array_merge($result, array_flatten($value)); 
                 } 
                 else { 
                   $result[$key] = $value; 
                 } 
               } 
              return $result; 
             } 
Solution-3: $input = array_map("unserialize", array_unique(array_map("serialize", $input)));

我想将此数组组合成一个单维数组,并从中删除重复值。我可以通过每个数组循环获得结果,但是执行时间会更长,我希望必须有一些简单的解决方案。谁能解决这个问题,谢谢。

【问题讨论】:

  • 听起来不错。那么你尝试了什么?
  • 更新了我的问题,请查看。
  • 单数组是什么意思?您不能使此数据适合平面数组。您必须至少有一个级别的深度数组。此外,如果您使用 var_export 而不是 print_r/var_dump 会很好,因为 var_export 可以复制粘贴到代码中。
  • 我正在从数据库中获取这些数组数据。

标签: php arrays sorting multidimensional-array


【解决方案1】:

请试试这个代码

$list = is your array;     
$flattern_array = array();
    $flat_array = function($item) use(&$flattern_array, &$flat_array){
          $keys = array_keys($item);
          if(is_array($item) && !in_array("role_id", $keys, TRUE)){
            foreach($item as $_item){
              $flat_array($_item);
            }
          }else{
              $flattern_array[] = $item;
          }
    };

    $flat_array($list);

   // Now $flattern_array have all items
   //Here we can remove duplicates from array
    $result = array_map("unserialize", array_unique(array_map("serialize", $flattern_array)));

【讨论】:

    【解决方案2】:

    我们不会为此数据集编写纯粹的自定义解决方案,而是首先创建一些通用函数,以便更轻松地处理通用数据

    我们从一个flatten 函数开始,它接受一个N 维数组并返回一个N-1 维数组。

    function flatten (array $xs) {
      return array_reduce
        ( $xs
        , 'array_merge'
        , []
        )
      ;
    }
    
    var_export (flatten ($data));
    
    // array (
    //   0 => 
    //     array ( 'role_id' => 2, 'name' => 'name1', 'email' => 'email1@somemail.com', ),
    //   1 => 
    //     array ( 'role_id' => 2, 'name' => 'name2', 'email' => 'email2@somemail.com', ),
    //   2 => 
    //     array ( 'role_id' => 2, 'name' => 'name3', 'email' => 'email3@somemail.com', ),
    //   3 => 
    //     array ( 'role_id' => 2, 'name' => 'name4', 'email' => 'email4@somemail.com', ),
    //   4 => 
    //     array ( 'role_id' => 2, 'name' => 'name3', 'email' => 'email3@somemail.com', ),
    //   5 => 
    //     array ( 'role_id' => 2, 'name' => 'name3', 'email' => 'email3@somemail.com', ),
    //   6 => 
    //     array ( 'role_id' => 2, 'name' => 'name2', 'email' => 'email2@somemail.com', ),
    //   7 => 
    //     array ( 'role_id' => 2, 'name' => 'name3', 'email' => 'email3@somemail.com', ),
    // )
    

    现在如果我们可以使用 PHP 的 array_unique 就好了,但它只适用于原始值。在这种情况下,我们需要一个函数来指定更复杂的匹配行为。为此,我们创建了自己的 array_unique_by 函数

    function array_unique_by (array $xs, callable $f) {
      return array_reduce
        ( $xs
        , function ($acc, $x) use ($f) {
            if ( array_search_by ( $acc
                                 , function ($y) use ($f, $x) {
                                     return call_user_func ($f, $x, $y);
                                   }
                                 )
                 === null
               )
              return array_merge ($acc, [ $x ]);
            else
              return $acc;
          }
        , []
        )
      ;
    }
    

    在我们继续之前,请注意我们介绍了array_search_by。与 PHP 的 array_unique 一样,PHP 的 array_search 也仅适用于原始值,因此我们需要一种方法来搜索复杂值,例如我们数据集中的值。

    function array_search_by (array $xs, callable $f) {
      foreach ($xs as $x) {
        if (call_user_func($f, $x) === true)
          return $x;
      }
      return null;
    }
    

    最后,为了让我们使用array_unique_by 函数,我们需要向它传递一个匹配 函数。这个函数将告诉array_unique_by 我们数据集中的哪些元素被认为是“匹配”。例如,我们将其称为 match_user,因为您的数据集中的元素看起来像是用户。

    function match_user ($a, $b) {
      return $a["role_id"] === $b["role_id"]
        && $a["name"] === $b["name"]
        && $a["email"] === $b["email"]
      ;
    }
    

    一切就绪后,我们现在可以编写一个非常简单的程序来实现您想要的结果

    var_export (array_unique_by (flatten ($data), 'match_user'));
    
    // array (
    //   0 => 
    //   array ( 'role_id' => 2, 'name' => 'name1', 'email' => 'email1@somemail.com', ),
    //   1 => 
    //   array ( 'role_id' => 2, 'name' => 'name2', 'email' => 'email2@somemail.com', ),
    //   2 => 
    //   array ( 'role_id' => 2, 'name' => 'name3', 'email' => 'email3@somemail.com', ),
    //   3 => 
    //   array ( 'role_id' => 2, 'name' => 'name4', 'email' => 'email4@somemail.com', ),
    // )
    

    备注

    上面的函数都是用函数式写的,用PHP很难表达。我努力为array_unique_by 找到合适的语法格式。关键是,您可以随心所欲地实现这些通用功能。这是array_unique_by 的另一种可能的实现,使用 PHP 程序员更熟悉的命令式样式。此实现的行为与上面定义的版本完全相同,但可能更好地向读者传达其意图

    function array_unique_by (array $xs, callable $f) {
      $acc = [];
      foreach ($xs as $x) {
        $match =
          array_search_by
            ( $acc
            , function ($y) use ($f, $x) {
                return call_user_func ($f, $x, $y);
              }
            )
          ;
        if ($match === null)
          array_push ($acc, $x);
      }
      return $acc;
    }
    

    最后,PHP 的 anonymous functions 的 lambda 语法也很笨拙。为了利用在 lambda 之外定义的变量,我们必须使用这种尴尬的 use ($f, $x) 语法。我们可以使用其他通用辅助函数来解决这个问题,比如下面介绍的partial

    function partial (callable $f, ...$xs) {
      return function (...$ys) use ($f, $xs) {
        return call_user_func_array
          ( $f
          , array_merge ($xs, $ys)
          )
        ;
      };
    }
    
    function array_unique_by (array $xs, callable $f) {
      $acc = [];
      foreach ($xs as $x) {
        $match =
          array_search_by
            ( $acc
            , partial ($f, $x)
            )
          ;
        if ($match === null)
          array_push ($acc, $x);
      }
      return $acc;
    }
    

    在上面,array_unique_by 的工作方式与其他实现完全相同,但更容易阅读。您可以继续使用它,直到您满意为止。

    这里的想法很简单:您可以使用泛型函数创建缺失的功能或抽象出烦恼。然后可以以各种优雅的方式组合这些功能,从而形成一个更易于读者理解的程序。

    性能

    我们的array_unique_by 函数利用了我们自己的array_search_by 函数。如果我们在脑海中想象正在经历的过程,我们输入中的每个元素都需要与我们正在构建的输出进行比较,$acc。我们在这里所做的“寻找匹配”是通过在$acc 的开头进行搜索,并逐个查看每个元素,直到找到潜​​在的匹配......

    如果我们的输入数据非常大,则此linear search 的性能配置文件非常差。对此进行优化的一种方法是将$acc 构建为binary search tree。但这当然意味着我们必须创建一个适合我们的数据集的。或者我们可以利用 PHP 的hashable 接口来减少工作量。这种实现受益于二分搜索,它比线性搜索快得多。

    这个练习留给读者。

    【讨论】:

      猜你喜欢
      • 2023-04-02
      • 1970-01-01
      • 2020-04-28
      • 2016-12-11
      • 2018-02-09
      • 1970-01-01
      • 2014-06-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多