配列のすべての要素を互いに比較したい。
$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
ランダムな値の繰り返し値を変更するには、配列を 2 回ループする必要があります。
$cont= 0;
foreach($char as $c){
foreach($char as $d){
if($c == $d){
//updating the value
$char[$cont] = rand(0,35);
}
}
$cont++;
}
しかし、ランダムな値も繰り返すことができるかどうかはわかりません。その場合、それほど単純ではありません。
このコードは、Rand() の PHP マニュアル ページから取得しました。
<?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);
アレイarray_count_values()
で最初に使用します。$char
その後、複数のエントリをすべてループしてランダム化できます。すべてのカウントが 1 になるまでチェックし続ける必要があります。ランダムでさえ、複製を再度作成する可能性があるためです。
この関数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
は結果です。この境界条件は、2 番目に単純な結果です (最初の単純な結果は、メンバーのない入力配列です)。
r
他のすべてのケースでは、ランダムな一意の値が必要です。あなたの質問では、0から35まで書いています。しかし、これは完全な話ではありません。入力配列に 36 個の重複した値があり、0 から 35 までの範囲の各数値が 1 回重複しているとします。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)
順序どおりにシャッフルして追加したい場合は、次の操作を実行できます。
shuffle($Nr);
これにより、質問で求めているように見えるランダム性が回答に戻るはずです。
これで、元の配列の一意の部分$Nu
とr
新しい値が に残ります$Nr
。これらの両方の配列をマージすると、キー => 値の関係を無視する結果の配列が得られます (配列は再インデックスされます)。
array_merge($Nu, $Nr);
たとえば、array(3, 4, 2, 1, 4, 0, 5, 0, 3, 5)
forの例で$N
は、次の結果が得られます。
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
も、配列内で一意である必要があります。したがって、一意の既存の番号に追加される新しい番号ごとに、重複した番号のキーであったキーを使用する必要があります。重複した番号のすべてのキーを取得するには、元の配列のキーのセットが、重複した番号の一致のすべてのキーのセットによって削減されます (「一意の配列」のキー$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
ただし、キーは元の値の最初の出現に対して保持されているため、順序は変更されています。最初にすべての以前に一意の値、次にすべての新しい値です。ただし、新しい値を適切な場所に追加したい場合があります。そのためには、新しい値の元のキーの順序を取得する必要があります。これは、順序をキーでマッピングし、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
(keyed 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
)
ランダムな配列を作成するには、次の 2 つのオプションをお勧めします。
<?php
$questions = array(1, 2, 3, 4, 5, ..., 34, 35);
$questions = shuffle($questions);
?>
その後、上位 10 個の要素を選択します。
you can try this code to replace any repeated value.
for ($i = 0; $i < count($char); $i++) {
for ($n = 0; $n < count($char); $n++) {
if($char[$i] == $char[$n]){
$char[$i] = rand(0,35);
}
}
}