如何从PHP中的multidimensional array中删除重复的值
如何从PHP中的multidimensional array中删除重复的值?
示例数组:
Array ( [0] => Array ( [0] => abc [1] => def ) [1] => Array ( [0] => ghi [1] => jkl ) [2] => Array ( [0] => mno [1] => pql ) [3] => Array ( [0] => abc [1] => def ) [4] => Array ( [0] => ghi [1] => jkl ) [5] => Array ( [0] => mno [1] => pql ) )
这是另一种方式。 没有中间variables被保存。
我们使用这个方法去重复各种重叠查询的结果。
$input = array_map("unserialize", array_unique(array_map("serialize", $input)));
从5.2.9开始,如果使用SORT_REGULAR
标志,可以使用array_unique()
:
array_unique($array, SORT_REGULAR);
这使得函数比较元素的相等性,就像$a == $b
被使用一样,这对你的情况来说是完美的。
产量
Array ( [0] => Array ( [0] => abc [1] => def ) [1] => Array ( [0] => ghi [1] => jkl ) [2] => Array ( [0] => mno [1] => pql ) )
请记住, 该文档指出:
array_unique()
不适用于multidimensional array。
我有一个类似的问题,但我find了一个100%的工作解决scheme。
<?php $arr=""; $arr[0]['id']=0; $arr[0]['titel']="ABC"; $arr[1]['id']=1; $arr[1]['titel']="DEF"; $arr[2]['id']=2; $arr[2]['titel']="ABC"; $arr[3]['id']=3; $arr[3]['titel']="XYZ"; echo "<pre>"; print_r($arr); echo "unique*********************<br/>"; print_r(super_unique($arr,'titel')); function super_unique($array,$key) { $temp_array = array(); foreach ($array as &$v) { if (!isset($temp_array[$v[$key]])) $temp_array[$v[$key]] =& $v; } $array = array_values($temp_array); return $array; } ?>
其他方式。 将保存密钥以及。
function array_unique_multidimensional($input) { $serialized = array_map('serialize', $input); $unique = array_unique($serialized); return array_intersect_key($input, $unique); }
用户对array_unique()文档的评论有许多解决scheme。 这是其中之一:
在rbnsn点com的kenrbnsn
2005年9月27日12:09另一个Array_Unique用于multidimensional array。 我只在二维数组上进行过testing,但是可能会将其推广为更多,或者使用recursion。
这个函数使用serialize,array_unique和unserialize函数来完成这项工作。
function multi_unique($array) { foreach ($array as $k=>$na) $new[$k] = serialize($na); $uniq = array_unique($new); foreach($uniq as $k=>$ser) $new1[$k] = unserialize($ser); return ($new1); }
这是从http://ca3.php.net/manual/en/function.array-unique.php#57202 。
如果“删除重复项”意味着“删除重复项,但让其中一个”,解决办法可能是首先在“标识符列”上应用array_unique(...)
,然后删除原始数组中的所有项已从列数组中移除:
$array = [ [ 'id' => '123', 'foo' => 'aaa', 'bar' => 'bbb' ], [ 'id' => '123', 'foo' => 'ccc', 'bar' => 'ddd' ], [ 'id' => '567', 'foo' => 'eee', 'bar' => 'fff' ] ]; $ids = array_column($array, 'id'); $ids = array_unique($ids); $array = array_filter($array, function ($key, $value) use ($ids) { return in_array($value, array_keys($ids)); }, ARRAY_FILTER_USE_BOTH);
结果是:
Array ( [0] => Array ( [id] => 123 [foo] => aaa [bar] => bbb ) [2] => Array ( [id] => 567 [foo] => eee [bar] => fff ) )
如果你需要消除特定键上的重复,比如一个mysqli id,这里有一个简单的function
function search_array_compact($data,$key){ $compact = []; foreach($data as $row){ if(!in_array($row[$key],$compact)){ $compact[] = $row; } } return $compact; }
奖励积分您可以传递一个键数组并添加一个外部的foreach,但是每个额外的键会慢两倍。
如果你有这样一个数组:
(用户是数组的名称)
Array=> [0] => (array) 'user' => 'john' 'age' => '23' [1] => (array) 'user' => 'jane' 'age' => '20' [2]=> (array) 'user' => 'john' 'age' => '23'
你想删除重复的…然后:
$serialized = array(); for ($i=0; $i < sizeof($users); $i++) { $test = in_array($users['user'], $serialized); if ($test == false) { $serialized[] = $users['user']; } }
可以是一个解决scheme:P
一个易于阅读的解决scheme,可能不是最有效的:
function arrayUnique($myArray){ if(!is_array($myArray)) return $myArray; foreach ($myArray as &$myvalue){ $myvalue=serialize($myvalue); } $myArray=array_unique($myArray); foreach ($myArray as &$myvalue){ $myvalue=unserialize($myvalue); } return $myArray; }
只要使用SORT_REGULAR选项作为第二个参数。
$uniqueArray = array_unique($array, SORT_REGULAR);
序列化和唯一的替代scheme
$test = [ ['abc','def'], ['ghi','jkl'], ['mno','pql'], ['abc','def'], ['ghi','jkl'], ['mno','pql'], ]; $result = array_reduce( $test, function($carry,$item){ if(!in_array($item,$carry)) { array_push($carry,$item); } return $carry; }, [] ); var_dump($result); /* php unique.php array(3) { [0] => array(2) { [0] => string(3) "abc" [1] => string(3) "def" } [1] => array(2) { [0] => string(3) "ghi" [1] => string(3) "jkl" } [2] => array(2) { [0] => string(3) "mno" [1] => string(3) "pql" } }
* /
如果你有这样的数组
data = array ( [0] => array ( [subject] => a [object] => c ), [1] => array ( [subject] => b [object] => d ), [2] => array ( [subject] => d [object] => b ), [3] => array ( [subject] => d [object] => c ), [4] => array ( [subject] => c [object] => a ), [5] => array ( [subject] => c [object] => d ) )
你想获得这样的数组:
data = array ( [0] => array ( [subject] => a [object] => c ), [1] => array ( [subject] => b [object] => d ), [2] => array ( [subject] => d [object] => c ) )
要么
data = array ( [0] => array ( [subject] => d [object] => b ), [1] => array ( [subject] => c [object] => a ), [2] => array ( [subject] => c [object] => d ) )
下面的代码可以帮助
$data1 = array(); $data1 = $data; for($q=0;$q<count($data);$q++) { for($p=0;$p<count($data1);$p++) { if (($data[$q]["subject"] == $data1[$p]["object"]) && ($data[$q]["object"] == $data1[$p]["subject"])) { $data1[$p]["subject"] = $data[$q]["subject"]; $data1[$p]["object"] = $data[$q]["object"]; } } } $data1 = array_values(array_map("unserialize", array_unique(array_map("serialize", $data1)))); $data = $data1;
我已经给了这个问题很多思考,并确定最佳的解决scheme应该遵循两个规则。
- 对于可伸缩性,请修改arrays; 没有复制到一个新的数组
- 为了performance,每一次比较只能做一次
考虑到这一点,并考虑到所有PHP的怪癖,下面是我提出的解决scheme。 与其他一些答案不同的是,它能够根据您想要的任何关键字来移除元素。 input数组有望成为数字键。
$count_array = count($input); for ($i = 0; $i < $count_array; $i++) { if (isset($input[$i])) { for ($j = $i+1; $j < $count_array; $j++) { if (isset($input[$j])) { //this is where you do your comparison for dupes if ($input[$i]['checksum'] == $input[$j]['checksum']) { unset($input[$j]); } } } } }
唯一的缺点是当迭代完成时键没有按顺序排列。 如果你以后只使用foreach循环,这不是一个问题,但如果你需要使用for循环,你可以把$input = array_values($input);
在上面重新编号键之后。
正如人们所说的array_unique()
非常慢,这是一个片段,我用于一个级别的multidimensional array。
$serialized_array = array_map("serialize", $input); foreach ($serialized_array as $key => $val) { $result[$val] = true; } $output = array_map("unserialize", (array_keys($result)));
引用第一个用户在php.net中贡献了array_unique()
函数页面的注释
很多人问我如何做独特的multidimensional array。 我已经从你的评论中引用了它,这对我有所帮助。
首先,感谢@jeromegamez @daveilers的解决scheme。 但是每次我给出答案的时候,他们都问我这个“序列化”和“反序列化”是如何工作的。 这就是为什么我想和你分享这个原因,这样可以帮助更多的人理解这个背后的概念。
我正在解释为什么我们在步骤中使用“序列化”和“反序列化”:
步骤1:将multidimensional array转换为一维数组
要将multidimensional array转换为一维数组,首先要生成数组内所有元素(包括嵌套数组)的字节stream表示forms。 serialize()函数可以生成一个值的字节stream表示。 要生成所有元素的字节stream表示forms,请在array_map()函数内调用serialize()函数作为callback函数。 无论multidimensional array有多less层,结果都是一维数组。
第2步:使值独一无二
要使这个一维数组唯一,请使用array_unique()函数。
第3步:将其还原为multidimensional array
尽pipe数组现在是唯一的,但是这些值看起来像是字节stream表示。 要将其还原为multidimensional array,请使用unserialize()函数。
$input = array_map("unserialize", array_unique(array_map("serialize", $input)));
再次感谢所有这一切。