我想比较数组中的每个元素。
$char=array();
for($i=0;$i<=10;$i++)
{
$char[$i]=rand(0,35);
}
我想比较$ char数组的每个元素。如果有任何重复值,它应该更改值并选择另一个在数组中应该唯一的随机值。
答案 0 :(得分:7)
在这个特殊的例子中,可能值的范围非常小,最好以另一种方式做到这一点:
$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
答案 1 :(得分:0)
要更改随机值的任何重复值,您应该遍历数组两次:
$cont= 0;
foreach($char as $c){
foreach($char as $d){
if($c == $d){
//updating the value
$char[$cont] = rand(0,35);
}
}
$cont++;
}
但我不知道的是,随机值是否也可以重复。在那种情况下,它不会那么简单。
答案 2 :(得分:0)
<?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);
答案 3 :(得分:0)
首先在array_count_values()
阵列上使用$char
。
然后你可以循环所有超过1的条目并随机化它们。你必须继续检查,直到所有计数都是1 tho。因为即使是随机也可能会重新制作副本。
答案 4 :(得分:0)
我建议制作随机数组的两个选项:
<?php
$questions = array(1, 2, 3, 4, 5, ..., 34, 35);
$questions = shuffle($questions);
?>
之后你选择前10个元素。
答案 5 :(得分:0)
您可以尝试使用此代码替换任何重复的值。
for ($i = 0; $i < count($char); $i++) {
for ($n = 0; $n < count($char); $n++) {
if($char[$i] == $char[$n]){
$char[$i] = rand(0,35);
}
}
}
答案 6 :(得分:0)
函数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)
时随机添加这些新值,您可以执行以下操作:
shuffle($Nr);
这应该会使你似乎的随机性在你的问题中要求回到答案中。
现在,您可以在$Nu
中获得原始数组r
和 $Nr
中新值的独特部分。合并这两个数组将为您提供一个忽略key =&gt;的结果数组。值关系(数组是重新索引):
array_merge($Nu, $Nr);
例如array(3, 4, 2, 1, 4, 0, 5, 0, 3, 5)
的示例$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
。
关系或键=&gt;由于array_merge()
,值不会保留,它会重新索引数字键。另外,Nr
键中的唯一数字旁边也需要在数组中是唯一的。因此,对于添加到unqique现有数字的每个新数字,需要使用一个密钥作为重复数字的密钥。为了获得重复数字的所有密钥,原始数组中的密钥集减少了所有重复数字匹配的密钥集(&#34;唯一数组中的密钥&#34; $Nu
):
$Kr = array_keys(array_diff_assoc($N, $Nu));
现在可以使用这些键来锁定现有结果$Nr
。 PHP中用于设置数组所有键的函数是使用函数array_combine()
:
$Nr = array_combine($Kr, $Nr);
这允许使用key =&gt;获得结果使用数组联合运算符(+
)保存的值关系:
$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
(键控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
)