$listData = [
'111' => ['a', 'b', 'c', 'a'],
'222' => ['d', 'e', 'f', 'f', 'b'],
'333' => ['g', 'h'],
'444' => ['i', 'j'],
...
];
定义一个函数,传入$listData 如果111里面的元素,和 222/333/444… 里面的元素有重复,返回false 如果222里面的元素,和 111/333/444… 里面的元素有重复,返回false 如果333里面的元素,和 111/222/444… 里面的元素有重复,返回false 如果 … 允许 111/222/333/444 自己里面的元素重复,返回true 其他情况返回true
已知: $listData长度未知 111/222/333/444… 的长度未知 111/222/333/444… 里的元素为字符串和数字
优化过程
$listData = [
'111' => ['a', 'b', 'c', 'a'],
'222' => ['d', 'e', 'f', 'f', 'z'],
'333' => ['g', 'h'],
'444' => ['i', 'j'],
'555' => ['p', 'q', 'x'],
'666' => ['k', 'l', 'n', 'm'],
'777' => ['o', 'r', 's'],
'888' => ['t', 'u', 'v'],
'999' => ['w', 'y']
];
/**
* 最简单的方式
* @param $listData
* @return bool
* @spent 0.001424 seconds
*/
function checkRepeat($listData)
{
foreach ($listData as $key => $row) {
foreach ($row as $val) {
foreach ($listData as $subKey => $subRow) {
if ($key != $subKey && in_array($val, $subRow)) {
return false;
}
}
}
}
return true;
}
$beginTime = microtime(true);
$result = checkRepeat($listData);
$endTime = microtime(true);
echo "spent " . round($endTime - $beginTime, 6) . " seconds";
var_dump($result);
echo "<br /><br /><br />";
/**
* 使用了array_intersect做交集比较
* @param $listData
* @return bool
* @spent 0.000594 seconds
*/
function checkRepeat2($listData)
{
foreach ($listData as $key => $row) {
foreach ($listData as $subKey => $subRow) {
if ($key != $subKey && array_intersect($row, $subRow)) {
return false;
}
}
}
return true;
}
$beginTime = microtime(true);
$result = checkRepeat2($listData);
$endTime = microtime(true);
echo "spent " . round($endTime - $beginTime, 6) . " seconds";
var_dump($result);
echo "<br /><br /><br />";
/**
* 使用了array_intersect做交集,删除重复比较
* @param $listData
* @return bool
* @spent 0.000305 seconds
*/
function checkRepeat3($listData)
{
$subListData = $listData;
foreach ($listData as $key => $row) {
unset($subListData[$key]);
foreach ($subListData as $subKey => $subRow) {
if (array_intersect($row, $subRow)) {
return false;
}
}
}
return true;
}
$beginTime = microtime(true);
$result = checkRepeat3($listData);
$endTime = microtime(true);
echo "spent " . round($endTime - $beginTime, 6) . " seconds";
var_dump($result);
echo "<br /><br /><br />";
/**
* 使用array_merge合并后在做交集
* @param $listData
* @return bool
* @spent 0.000194 seconds
*/
function checkRepeat4($listData)
{
$check_arr = $listData;
foreach ($listData as $key => $val) {
// 删除当前key
unset($check_arr[$key]);
if ($check_arr) {
// 合并删除后的数组,判断是否存在交集
//As PHP 5.6 you can use array_merge + "splat" operator to reduce a bidimensonal array to a simple array:
if (array_intersect($val, array_merge(...$check_arr))) {
return false;
}
}
}
return true;
}
$beginTime = microtime(true);
$result = checkRepeat4($listData);
$endTime = microtime(true);
echo "spent " . round($endTime - $beginTime, 6) . " seconds";
var_dump($result);
echo "<br /><br /><br />";
/**
* https://segmentfault.com/q/1010000007527180 @shiji 的答案
* 子数组先去重再合并的结果数量 和 先合并子数组再去重的结果数量 做比较。
* 如果是相同的,意味着不存在跨子数组的重复,只存在子数组内部重复,所以`True`
* @param $listData
* @return bool
* @spent 0.000153 seconds 但是当有重复项时速度很慢
*/
function checkRepeat5($listData)
{
$result = array();
foreach ($listData as $line) {
//子数组内部去重,再组装回原来的格式
$result[] = array_unique($line);
}
return count(array_merge(...$result)) === count(array_unique(array_merge(...$listData)));
}
$beginTime = microtime(true);
$result = checkRepeat5($listData);
$endTime = microtime(true);
echo "spent " . round($endTime - $beginTime, 6) . " seconds";
var_dump($result);
echo "<br /><br /><br />";