我有一个逗号分隔的数字列表,我正在将其转换为数组,我想知道的数字列表是,如果列出的数字遵循数字的自然顺序,你知道,下一个和上一个之间的差异正好1
。
我想选择列表的第一个数字,如果不是列表服从自然顺序,我选择第二个。
这是我的代码。
<?php
error_reporting(0);
/**
Analyze numbers
Condition 1
if from number to the next has a difference of 1,then pick the first number in the list
Condition 2
if from one number the next,a difference of greater than 1 was found,then pick next from first
Condition 3
if list contains only one number,pick the number
*/
$number_picked = null;
$a = '5,7,8,9,10';
$b = '2,3,4,5,6,7,8,9,10';
$c = '10';
$data = explode(',', $b);
$count = count($data);
foreach($data as $index => $number)
{
/**
If array has exactly one value
*/
if($count == 1){
echo 'number is:'.$number;
exit();
}
$previous = $data[($count+$index-1) % $count];
$current = $number;
$next = $data[($index+1) % $count];
$diff = ($next - $previous);
if($diff == 1){
$number_picked = array_values($data)[0];
echo $number_picked.'correct';
}
elseif($diff > 1){
$number_picked = array_values($data)[1];
echo $number_picked.'wrong';
}
}
?>
我遇到的问题是弄清楚如何测试所有数组元素的差异。
不需要循环,一点数学在这里会有所帮助。一旦你的数字在一个数组中:
$a = explode(',', '5,7,8,9,10');
将它们传递给此函数:-
function isSequential(array $sequence, $diff = 1)
{
return $sequence[count($sequence) - 1] === $sequence[0] + ($diff * (count($sequence) - 1));
}
如果数组中的数字遵循自然序列,则该函数将返回 true。您甚至应该能够使用 $diff 参数针对数字之间的不同间距进行调整,例如 2, 4, 6, 8
等,尽管我还没有彻底测试过。
看到它工作。
请记住,仅当您的数字列表从小到大排序时,这才有效。
尝试使用函数来解决这个问题...这样:
<?php
error_reporting(0);
/**
Analyze numbers
Condition 1
if from number to the next has a difference of 1,then pick the first number in the list
Condition 2
if from one number the next,a difference of greater than 1 was found,then pick next from first
Condition 3
if list contains only one number,pick the number
*/
$number_picked = null;
$a = '5,7,8,9,10';
$b = '2,3,4,5,6,7,8,9,10';
$c = '10';
function test($string) {
$data = explode(',', $string);
if(count($data) === 1){
return 'number is:'.$number;
}
foreach($data as $index => $number)
{
$previous = $data[($count+$index-1) % $count];
$current = $number;
$next = $data[($index+1) % $count];
$diff = ($next - $previous);
if($diff == 1){
$number_picked = array_values($data)[0];
return $number_picked.'correct';
}
elseif($diff > 1){
$number_picked = array_values($data)[1];
return $number_picked.'wrong';
}
}
}
echo test($a);
echo test($b);
echo test($c);
?>
你已经知道如何分解列表,所以我会跳过它。您已经处理了一个项目,所以我也会跳过它。
剩下的就是检查数组的其余部分。基本上;有两种可能的结果值:第一个元素或第二个元素。因此,我们将首先保存这两个:
$outcome1 = $list[0];
$outcome2 = $list[1];
接下来,我们将遍历这些项目。我们将记住最后找到的项目,并确保新旧之间的差值为 1。如果是,我们继续。如果不是,我们将中止并立即返回 $outcome 2。
如果我们到达列表的末尾而不中止,它自然是有序的,所以我们返回 $outcome 1。
$lastNumber = null;
foreach( $items as $number ) {
if($lastNumber === null || $number - $lastNumber == 1 ) {
// continue scanning
$lastNumber = $number;
}
else {
// not ordened
return $outcome2;
}
}
return $outcome1; // scanned everything; was ordened.
(注意:代码未测试)
为了避免访问上一个或下一个元素的头痛,并确定它是否仍在数组中,请使用以下事实:在自然排序中,项目 i 和第一项的差为 i。
此外,您调用条件 3 的极端情况在循环外部比在循环内部更容易处理。但更容易的是,我们表征自然有序列表的方式适用于 1 项列表:
$natural = true;
for($i=1; $i<$count && $natural; $i++)
$natural &= ($data[$i] == $data[0] + $i)
$number = $natural ? $data[0] : $data[1];
对于$count == 1
循环永远不会进入,因此$natural
保持true
:你选择第一个元素。