$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... 裡的元素為字串和數字
我自己實現了一下,感覺演算法很糟,請問有沒有其他方法
function test ($array) { $tempValueList = []; foreach ($array as $key => $valueList) { foreach ($valueList as $value) { $tempValueList[] = $key . '~' . $value; } } $result = true; foreach ($array as $key => $valueList) { foreach ($valueList as $value) { foreach ($tempValueList as $_value) { $pos = strpos($_value, '~'); $_key = substr($_value, 0, $pos); $_val = substr($_value, $pos + 1); if ($key == $_key) { continue; } if ($_val == $value) { $result = false; break 3; } } } } return $result;}
回複內容:
$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... 裡的元素為字串和數字
我自己實現了一下,感覺演算法很糟,請問有沒有其他方法
function test ($array) { $tempValueList = []; foreach ($array as $key => $valueList) { foreach ($valueList as $value) { $tempValueList[] = $key . '~' . $value; } } $result = true; foreach ($array as $key => $valueList) { foreach ($valueList as $value) { foreach ($tempValueList as $_value) { $pos = strpos($_value, '~'); $_key = substr($_value, 0, $pos); $_val = substr($_value, $pos + 1); if ($key == $_key) { continue; } if ($_val == $value) { $result = false; break 3; } } } } return $result;}
看了看,之前的那倆答案都是不能用的。LZ真是苦命。。
我對子數組的定義是像 ['a', 'b', 'c', 'a'] 這樣的單個數組。
我的答案:
$result = array();foreach ($listData as $line) { //子數組內部去重,再組裝回原來的格式 $result[] = array_unique($line);}//子數組先去重再合并的結果數量 和 先合并子數組再去重的結果數量 做比較。//如果是相同的,意味著不存在跨子數組的重複,只存在子數組內部重複,所以`True`var_dump(count(array_merge(...$result)) === count(array_unique(array_merge(...$listData))));
我這個答案調用系統函數次數比較多,看起來簡潔一些,但是PHP array_xxx 這類函數很大一部分效能是不具備優勢的,如果不用這些函數,能相對程度提高運行效率。
目前, @springhack 的效率是最高的。而且在各種情形下都能保持最高效率。
方便理解的輔助參考資訊:
未經處理資料:
$listData = [ '111' => ['a', 'b', 'c', 'a'], '222' => ['d', 'e', 'f', 'f', 'b'], '333' => ['g', 'h'], '444' => ['i', 'j']];
然後 $result 最終是這樣的:
$listData = [ '111' => ['a', 'b', 'c'], '222' => ['d', 'e', 'f', 'b'], '333' => ['g', 'h'], '444' => ['i', 'j']];
子數組先去重再合并的結果
Array( [0] => a [1] => b [2] => c [3] => d [4] => e [5] => f [6] => b [7] => g [8] => h [9] => i [10] => j)
用於和上面進行數量(數組元素數量)比較的,所謂的“先合并子數組再去重的結果”:
Array( [0] => a [1] => b [2] => c [4] => d [5] => e [6] => f [9] => g [10] => h [11] => i [12] => j)
迴圈一次,當前元素和其它所有元素求交集,代碼如下:
function isExistsInOther($data) { $temp = []; $isExists = true; foreach ($data as $key=>$value) { $temp = $data; unset($temp[$key]); if(!$isExists) break; @array_walk($temp,function($v,$k) use($value,&$isExists){ if($isExists) { $intersect = array_intersect($v,$value); if(!empty($intersect)) { $isExists = false; } } }); } return $isExists; } $listData = [ '111' => ['a', 'k', 'c', 'a'], '222' => ['d', 'e', 'f', 'f', 'b'], '333' => ['g', 'e'], '444' => ['i', 'j'] ]; $result = isExistsInOther($listData); var_dump($result); //true 無交集 //false 有交集
/** * [checkRepeat 檢查每個key的數組值是否與其它的有重複值] * @param [type] $listData [檢查的數組] * @return [type] [array] */function checkRepeat($listData) { foreach($listData as $key =>$val) { $check_arr = $listData; // 刪除當前key unset($check_arr[$key]); // 合并刪除後的數組 $check_arr = array_merge(...$check_arr); // 判斷是否存在交集 $rs[$key] = count(array_intersect($val, $check_arr)) > 0 ? false : true ; } return $rs;}$listData = [ '111' => ['a', 'b', 'c', 'a'], '222' => ['d', 'e', 'f', 'f', 'b'], '333' => ['g', 'h'], '444' => ['i', 'j'],];$rs = checkRepeat($listData);
function check($arr){ $chk = []; foreach ($arr as $k => $v) foreach ($v as $i) { if (isset($chk[$i] && $chk[$i] != $k) return false; $chk[$i] = $k; } return true;}
爪機碼字,應該是效率最高的,自己調試下。
既然上面都給了答案,我給你補充一下,多維陣列去重
/** * 多維陣列去重 * @param array * @return array */function super_unique($array){ $result = array_map("unserialize", array_unique(array_map("serialize", $array))); foreach ($result as $key => $value) { if ( is_array($value) ) { $result[$key] = super_unique($value); } } return $result;}
多維陣列去重
$listData = array_values($listData);foreach ($listData as $k => $v) { foreach ($listData as $n => $m) { if($k == $n) continue; if(array_intersect($v , $m)){ echo $k.$n.'false
'; } else{ echo $k.$n.'true
'; } }}
我的答案(原理:迴圈求交集):
['a', 'b', 'c', 'a'], '222' => ['d', 'e', 'f', 'f','b'], '333' => ['g', 'h','c'], '444' => ['i', 'j']];function jiaoji($array){ $listData = array_values($array); $list = []; for ($i = 0; $i < count($listData); $i++) { for ($j = $i+1; $j < count($listData); $j++) { $list[] = array_intersect($listData[$i],$listData[$j]); } } $result = array_filter($list); return count($result)==0;}var_dump(jiaoji($list));//bool(false)?>
能不能這樣理解 只要這個數組裡面的值相互之間有交集 那就返回false 。。。
array_intersect()函數好像可以用。但是問題就是在於將一個數組裡面的值變成小數組傳值。
['a', 'b', 'c', 'a'], '222' => ['d', 'e', 'f', 'f', 'b'], '333' => ['g', 'h'], '444' => ['i', 'j'], ...];function getArr($listData){ $isUnsetFirstKey = false; $len = count($listData); if($len<=1) return false; $firstKey = key($listData); $firstArr = array_unique($listData[$firstKey]); $newList = $listData; unset($newList[$firstKey]); foreach ($newList as $key => $val) { $arr = array_unique($val); $newarr = array_merge($firstArr,$arr); if(count($newarr) != count(array_unique($newarr))){ $isUnsetFirstKey = true; unset($newList[$key]); echo $key . "
"; } } if($isUnsetFirstKey) echo $firstKey . "
"; getArr($newList);}getArr($listData);?>
我的答案,看看吧,很厲害的
一維數組和二維數組類似, 在內部做判斷, 下面是二維數組的方法, 一維數組略過
比較數組合并之前和之後(之後取unique)的數組長度
function check_repeat($arr){ $after_arr = []; // 對比自身 foreach($arr as $index => $value){ $arr[$index] = $after_arr = array_unique($value); if(count($value) !== count($after_arr)){ return true; } } // 對比其他 $temp = array_shift($arr); $cnt = count($temp); foreach ($arr as $index => $value) { $cnt += count($value); $temp = array_merge($temp, $value); } return $cnt !== count(array_unique($temp)) ? true : false;}$listData = [ '111' => ['a', 'b', 'c',], '222' => ['d', 'e', 'f',], '333' => ['g', 'h'], '444' => ['i', 'j'],];var_dump(check_repeat($listData));
function test($listData) { $result = array_map('array_unique', $listData); foreach ($result as $key => $value) { $keys = array_values(array_diff(array_keys($result),[$key])); for($i = 0; $i <= count($keys); $i ++) { $data = array_merge_recursive($data,$result[$keys[$i]]); if ($i == (count($keys) -1) ) { $res = array_intersect($value, $data); } } $data = []; } return !empty($res) === true ? false : true;}
['a', 'b', 'c', 'a'], '222' => ['d', 'e', 'f', 'f', 'b'], '333' => ['g', 'h'], '444' => ['i', 'j'],];$temp = array();foreach ($listData as $key => $xxx) { foreach ($xxx as $value) { if (in_array($value, $temp)) { echo $value.' from '.$key.' is in array'; exit(); } } $temp = array_merge($temp, $xxx);}echo 'You should get a True!';
沒幾行,滿足需求。
還原之前那個
shiji 的答案
先array_pop,取出最後一項。再取items數組的並集。if並集與最後一項有交集則返回true(表重複)。迴圈執行。
根據 @大嗚 的演算法改良了一下。
function checkRepeat2($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;}
不知道是不是這樣:
$new_arr = [];foreach ($listData as $key => $value) { foreach ($value as $k => $v) { $kv = $k . $v; if (in_array($kv, $new_arr)) { echo '有重複';exit; } else { $new_arr[] = $kv; } }}