繁体   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