簡體   English   中英

如何將數組的每個元素相互比較?

[英]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為從0count(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 ),而且到目前為止,它們也不得成為NNu一部分。

要實現此目的,您只需要創建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
)

最后,這可能是回答您問題的最簡單方法。 希望這可以幫助您回答問題。 請記住以下幾點:

  • 划分您的問題:
    1. 您想知道一個值是否不合理array_unique()在這里可以為您提供幫助。
    2. 您要創建X個新的唯一數字/值。 array_diff()在這里為您提供幫助。
  • 對齊流程:
    1. 首先獲取唯一編號。
    2. 首先獲取新號碼。
    3. 同時使用兩者來處理原始數組。

像這個例子:

// 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM