简体   繁体   English

如何判断以逗号分隔的数字列表是否遵循数字的自然顺序

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

I have a comma delimited list of numbers which i am converting into an array and what i want to know about the list of numbers is if the numbers listed obey a natural ordering of numbers,you know,have a difference of exactly 1 between the next and the previous. 我有一个逗号分隔的数字列表,我将其转换成数组,而我想知道的数字列表是,如果列出的数字服从数字的自然顺序,那么下一个之间的差值就是1和以前的。

If its true the list obeys the natural ordering,i want to pick the first number of the list and if not the list obeys not the natural order,i pick the second. 如果列表为真,则服从自然顺序,我想选择列表的第一个数字;如果列表不服从自然顺序,则我选择第二个。

This is my code. 这是我的代码。

<?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';
  }
}
?>

The problem i am having is to figure out how to test the difference for all array elements. 我遇到的问题是弄清楚如何测试所有数组元素的差异。

Try using a function to solve this... Like so: 尝试使用函数来解决此问题...像这样:

<?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);
?>

You already know how to explode the list, so I'll skip that. 您已经知道如何展开列表,因此我将跳过它。 You already handle a single item, so I'll skip that as well. 您已经处理了一个项目,所以我也将跳过它。

What is left, is checking the rest of the array. 剩下的就是检查数组的其余部分。 Basically; 基本上; there's two possible outcome values: either the first element or the second. 有两个可能的结果值:第一个元素或第二个元素。 So we'll save those two first: 因此,我们将首先保存这两个:

$outcome1 = $list[0];
$outcome2 = $list[1];

Next, we'll loop over the items. 接下来,我们将遍历所有项目。 We'll remember the last found item, and make sure that the difference between the new and the old is 1. If it is, we continue. 我们将记住最后找到的项目,并确保新旧项目之间的差异为1。如果是,则继续。 If it isn't, we abort and immediately return $outcome2. 如果不是,我们中止并立即返回$ outcome2。

If we reach the end of the list without aborting, it's naturally ordered, so we return $outcome1. 如果我们在不终止的情况下到达列表的末尾,它自然是有序的,因此我们返回$ outcome1。

$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.

(Note: code not tested) (注意:代码未经测试)

To avoid the headache of accessing the previous or next element, and deciding whether it still is inside the array or not, use the fact that on a natural ordering the item i and the first item have a difference of i. 为了避免访问上一个或下一个元素以及确定它是否仍在数组内的麻烦,请使用以下事实:在自然排序时,项i与第一个项的差为i。

Also the corner case you call condition 3 is easier to handle outside the loop than inside of it. 同样,调用条件3的拐角案例比在循环外部更容易处理。 But easier still, the way we characterize a natural ordered list holds for a 1-item list : 但更容易的是,我们表征自然有序列表的方式适用于1项列表:

$natural = true;
for($i=1; $i<$count && $natural; $i++)
    $natural &= ($data[$i] == $data[0] + $i)

$number = $natural ? $data[0] : $data[1];

For $count == 1 the loop is never entered and thus $natural stays true : you select the first element. 对于$count == 1 ,永远不会输入循环,因此$natural保持为true :选择第一个元素。

No loops are needed, a little bit of maths will help you here. 不需要循环,这里的一些数学将对您有所帮助。 Once you have your numbers in an array: 将数字放入数组后:

$a = explode(',', '5,7,8,9,10');

pass them to this function:- 将它们传递给此功能:

function isSequential(array $sequence, $diff = 1)
{
    return $sequence[count($sequence) - 1] === $sequence[0] + ($diff * (count($sequence) - 1));
}

The function will return true if the numbers in the array follow a natural sequence. 如果数组中的数字遵循自然顺序,则该函数将返回true。 You should even be able to adjust it for different spacings between numbers, eg 2, 4, 6, 8 , etc using the $diff parameter, although I haven't tested that thoroughly. 您甚至还可以使用$ diff参数针对数字之间的不同间距(例如2, 4, 6, 8等)进行调整,尽管我尚未对此进行全面测试

See it working . 看到它工作

Keep in mind that this will only work if your list of numbers is ordered from smallest to largest. 请记住,这仅在您的数字列表从最小到最大的顺序排列时才有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM