Php 将三维数组合并为单个数组并删除重复值?

Php 将三维数组合并为单个数组并删除重复值?,php,arrays,sorting,multidimensional-array,Php,Arrays,Sorting,Multidimensional Array,我得到的三维数组在不同的数组中有重复的值,我想将这个三维数组合并成一个数组,并删除最终数组中的重复值 function flatten (array $xs) { return array_reduce ( $xs , 'array_merge' , [] ) ; } var_export (flatten ($data)); // array ( // 0 => // array ( 'role_id' => 2, 'nam

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

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', ),
// )
我的阵列是:

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)));
我想将这个数组合并成一个一维数组,并从中删除重复的值。我可以通过每个数组循环得到结果,但执行时间会更长,我希望一定有一些简单的解决方案。任何人都可以解决此问题,谢谢。

请尝试此代码

$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)));

我们将从创建一些通用函数开始,而不是为这个数据集编写一个纯粹的定制解决方案,这些函数可以使处理一般数据变得更容易

我们从一个
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,那就太好了,但它只适用于原始值。在这种情况下,我们需要一个函数,它允许我们指定更复杂的匹配行为。为此,我们通过函数使我们自己的
数组成为唯一的

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;
      }
    , []
    )
  ;
}
在继续之前,请注意,我们引入了
数组搜索方法。与PHP的
array\u unique
一样,PHP也只适用于原始值,因此我们需要一种搜索复杂值的方法,如数据集中的值

function array_search_by (array $xs, callable $f) {
  foreach ($xs as $x) {
    if (call_user_func($f, $x) === true)
      return $x;
  }
  return null;
}
最后,为了使用
array\u unique\u by
函数,我们需要向它传递一个匹配函数。此函数将通过
我们的数据集的哪些元素被视为“匹配”来告诉
数组\u unique\u。作为一个例子,我们将其称为
match\u 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很难表达。我很难找到一个合适的语法格式为
数组\u unique\u by
。关键是,您可以根据需要实现这些通用函数。下面是另一个可能的
array\u unique\u实现,它是使用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的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\u unique\u by
的工作原理与其他实现完全相同,但更易于阅读。你可以一直使用它,直到你满意为止

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

性能

我们的
array\u unique\u by
功能利用了我们自己的
array\u search\u by
功能。如果我们在心里想象正在进行的过程,我们输入中的每个元素都需要与我们正在构建的输出进行比较,
$acc
。在这里,“查找匹配项”是通过在
$acc
开头搜索,然后逐个查看每个元素,直到找到潜在匹配项

如果我们的输入数据非常大,这将导致非常糟糕的性能状况。优化这一点的一种方法是将
$acc
构建为一个。但这当然意味着我们必须创建一个适合我们的数据集。或者我们可以利用PHP的接口来减少工作量。这种实现得益于二进制搜索,它比线性搜索快得多


这个练习留给读者。

听起来不错。那么你尝试了什么?更新了我的问题,请检查。你说的单数组是什么意思?无法使此数据适合平面阵列。您必须至少有一级深度数组。另外,如果您使用var_导出而不是print_r/var_dump,也会很好,因为var_导出可以复制粘贴到代码中。