如何判断逗号分隔的数字列表是否服从数字的自然顺序


How to tell if a comma delimited list of numbers obeys the natural order of numbers

我有一个逗号分隔的数字列表,我正在将其转换为数组,我想知道的数字列表是,如果列出的数字遵循数字的自然顺序,你知道,下一个和上一个之间的差异正好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:你选择第一个元素。