[英]How to compare every element of array with one another?
我想將數組的每個元素相互比較。
$char=array();
for($i=0;$i<=10;$i++)
{
$char[$i]=rand(0,35);
}
我想比較$ char數組的每個元素。 如果有任何重復的值,則應更改值並選擇另一個隨機值,該值在數組中應唯一。
在此特定示例中,可能值的范圍很小,最好以另一種方式執行此操作:
$allPossible = range(0, 35);
shuffle($allPossible);
// Guaranteed exactly 10 unique numbers in the range [0, 35]
$char = array_slice($allPossible, 0, 10);
或使用array_rand
的等效版本:
$allPossible = range(0, 35);
$char = array_rand(array_flip($allPossible), 10);
如果值的范圍更大,則此方法將非常浪費,您應該在每次迭代中檢查唯一性:
$char = array();
for ($i = 0; $i < 10; ++$i) {
$value = null;
// Try random numbers until you find one that does not already exist
while($value === null || in_array($value, $char)) {
$value = rand(0, 35);
}
$char[] = $value;
}
但是,這是一種概率方法,可能取決於rand
的輸出結果,這可能會花費很多時間(如果所需值的數量接近所有可能值的數量,這將特別糟糕) 。
另外,如果您要選擇的值數量比較大(比如說超過50個左右),那么in_array
可能會成為瓶頸。 在那種情況下,使用數組鍵檢查唯一性而不是值應該更快,因為搜索鍵的存在是恆定時間而不是線性時間:
$char = array();
for ($i = 0; $i < 100; ++$i) {
$value = null;
// Try random numbers until you find one that does not already exist
while($value === null || array_key_exists($char, $value)) {
$value = rand(0, 1000);
}
$char[$value] = $value;
}
$char = array_values($char); // reindex keys to start from 0
若要將任意重復的值更改為隨機值,應遍歷數組兩次:
$cont= 0;
foreach($char as $c){
foreach($char as $d){
if($c == $d){
//updating the value
$char[$cont] = rand(0,35);
}
}
$cont++;
}
但是我不知道是否也可以重復隨機值。 在那種情況下,事情不會那么簡單。
我已從PHP手冊頁的rand()那里獲取了這段代碼
<?php
function uniqueRand($n, $min = 0, $max = null)
{
if($max === null)
$max = getrandmax();
$array = range($min, $max);
$return = array();
$keys = array_rand($array, $n);
foreach($keys as $key)
$return[] = $array[$key];
return $return;
}
?>
此函數生成一個大小為$ n的數組,您可以像在rand中那樣設置最小值和最大值。
所以你可以像這樣利用它
uniqueRand(10, 0, 35);
首先在$char
數組上使用array_count_values()
。
之后,您可以循環所有大於1的條目並將其隨機化。 您必須繼續檢查,直到所有計數都等於1。 因為即使是隨機的,也可能會再次復制。
我建議使用兩種方法來制作隨機數組:
<?php
$questions = array(1, 2, 3, 4, 5, ..., 34, 35);
$questions = shuffle($questions);
?>
之后,您選擇前10個元素。
您可以嘗試使用此代碼替換任何重復的值。
for ($i = 0; $i < count($char); $i++) {
for ($n = 0; $n < count($char); $n++) {
if($char[$i] == $char[$n]){
$char[$i] = rand(0,35);
}
}
}
函數array_unique()
從數組中獲取所有唯一值,並以它們的首次出現作為鍵。
函數array_diff()
允許從一個數組中的另一個數組中刪除值。
根據您需要(或不需要)鍵輸入結果的方式或鍵的保留順序,您需要執行多個步驟。 通常,它按照我在以下段落中概述的方式工作(帶有PHP代碼示例):
在一個數組中,您有N
元素,其中Nu
是唯一的。
$N = array(...);
$Nu = array_unique($N);
隨機元素的數量r
你需要再更換是重復的次數N
減去的數Nu
。 由於N
的計數通常是一個有用的值,因此我也將其分配給nc
:
$nc = count($N);
$r = $nc - count($Nu);
這使r
為從0
到count(N) - 1
的整數:
0 : no duplicate values / all values are unique
1 : one duplicate value / all but one value are unique
...
count(N) - 1 : all duplicate values / no unique value
因此,如果您需要零個隨機值( $r === 0
),則輸入$N
為結果。 此邊界條件是第二個最簡單的結果(第一個簡單結果是沒有成員的輸入數組)。
對於所有其他情況,您需要r
隨機唯一值。 在您的問題中,您輸入的范圍是0到35。但這不是完整的故事。 想象一下,您的輸入數組有36個重復值,從0到35范圍內的每個數字都重復一次。 再次將0到35范圍內的隨機數添加到數組將再次創建重復項-保證。
取而代之的是,我讀到了您的問題,即您只是在尋找尚不屬於輸入數組的唯一值。
因此,您不僅需要r
隨機值( Nr
),而且到目前為止,它們也不得成為N
或Nu
一部分。
要實現此目的,您只需要創建count(N)
唯一值,請從其中刪除唯一值Nu
,以確保沒有重復的值Nu
。 由於這是理論上的最大值,而不是所需的確切數字,因此該數組用於從以下項中獲取恰好r
元素的切片:
$Nr = array_slice(array_diff(range(0, $nc - 1), $Nu), 0, $r);
如果您還想按順序排列range(0, $nc - 1)
來range(0, $nc - 1)
添加這些新值,則可以執行以下操作:
shuffle($Nr);
這應該將您似乎在問題中要求的隨機性帶回到答案中。
現在,您將剩下原始數組$Nu
的唯一部分以及$Nr
r
新值。 合並這兩個數組將為您提供一個結果數組,該數組將忽略key => value關系(該數組是重新索引的):
array_merge($Nu, $Nr);
例如,使用$N
的示例array(3, 4, 2, 1, 4, 0, 5, 0, 3, 5)
,得到的結果是:
Array
(
[0] => 3
[1] => 4
[2] => 2
[3] => 1
[4] => 0
[5] => 5
[6] => 7
[7] => 9
[8] => 6
[9] => 8
)
如您所見,所有唯一值(0-5)都在開頭,后面是新值(6-9)。 原始鍵不保留,例如,值5
的鍵原為6
,現在為5
。
由於array_merge()
,關系或鍵=>的值未保留,它會重新索引數字鍵。 同樣,在Nr
鍵中唯一編號旁邊也需要在數組中唯一。 因此,對於添加到不確定現有數字中的每個新數字,都需要使用一個密鑰,該密鑰是重復數字的密鑰。 為了獲得所有重復編號的鍵,對於重復編號的匹配項,將原始數組中的鍵集減少為all的鍵集(“唯一數組” $Nu
):
$Kr = array_keys(array_diff_assoc($N, $Nu));
現在可以使用這些鍵來鍵入現有結果$Nr
。 PHP中為數組設置所有鍵的函數是使用array_combine()
函數:
$Nr = array_combine($Kr, $Nr);
這樣就可以使用數組聯合運算符( +
)保留鍵=>值關系得到的結果:
$Nu + $Nr;
例如,使用上一個示例中的$N
,得出的結果是:
Array
(
[0] => 3
[1] => 4
[2] => 2
[3] => 1
[5] => 0
[6] => 5
[4] => 8
[7] => 6
[8] => 9
[9] => 7
)
如您現在所看到的,值5
保留了鍵6
,值0
保留了鍵5
在原始數組中,現在在輸出中也保留了鍵4
,而不是前面的示例中的鍵4
。
但是,由於現在已為首次出現的原始值保留了鍵,因此順序仍然更改:首先是所有先前唯一的值,然后是所有新值。 但是,您可能希望將新值添加到位。 為此,您需要獲取新值的原始鍵的順序。 可以通過按鍵映射順序並使用array_multisort()
根據該順序進行排序來完成。
因為這需要通過參數傳遞返回值,所以還需要其他臨時變量,我選擇以字母V開頭:
// the original array defines the order of keys:
$orderMap = array_flip(array_keys($N));
// define the sort order for the result with keys preserved
$Vt = $Nu + $Nr;
$order = array();
foreach ($Vt as $key => $value) {
$order[] = $orderMap[$key];
}
然后完成排序(此處帶有保留鍵):
// sort an array by the defined order, preserve keys
$Vk = array_keys($Vt);
array_multisort($order, $Vt, $Vk);
結果是:
array_combine($Vk, $Vt);
再次使用上面的示例值:
Array
(
[0] => 3
[1] => 4
[2] => 2
[3] => 1
[4] => 7
[5] => 0
[6] => 5
[7] => 8
[8] => 6
[9] => 9
)
此示例輸出很好地顯示了鍵從0到9的順序,因為它們在輸入數組中很好。 例如,與先前的輸出相比,您可以看到第一個添加的值7
(鍵4
)在第5個位置-與原始數組中鍵4
的值相同。 按鍵的順序也已獲得。
如果這是您追求的結果,則可以通過迭代原始數組鍵來縮短此步驟的路徑,並且如果每個鍵都不是任何重復值的第一個值,則可以從新值中彈出代替數組:
$result = array();
foreach ($N as $key => $value) {
$result[$key] = array_key_exists($key, $Nu) ? $Nu[$key] : array_pop($Nr);
}
再次使用示例數組值作為結果(與前一個有所不同,因為$Nr
被改組:
Array
(
[0] => 3
[1] => 4
[2] => 2
[3] => 1
[4] => 7
[5] => 0
[6] => 5
[7] => 8
[8] => 9
[9] => 6
)
最后,這可能是回答您問題的最簡單方法。 希望這可以幫助您回答問題。 請記住以下幾點:
array_unique()
在這里可以為您提供幫助。 array_diff()
在這里為您提供幫助。 像這個例子:
// original array
$array = array(3, 4, 2, 1, 4, 0, 5, 0, 3, 5);
// obtain unique values (1.)
$unique = array_unique($array);
// obtain new unique values (2.)
$new = range(0, count($array) - 1);
$new = array_diff($new, $unique);
shuffle($new);
// process original array (3.)
foreach ($array as $key => &$value) {
if (array_key_exists($key, $unique)) {
continue;
}
$value = array_pop($new);
}
unset($value, $new);
// result in $array:
print_r($array);
然后(由於shuffle($new)
示例)輸出:
Array
(
[0] => 3
[1] => 4
[2] => 2
[3] => 1
[4] => 9
[5] => 0
[6] => 5
[7] => 8
[8] => 7
[9] => 6
)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.