Как объединить последовательные номера в отсортированный список номеров? - PullRequest
3 голосов
/ 16 мая 2019

Я хочу объединить последовательность чисел в читаемую строку. Последовательные номера должны быть объединены следующим образом '1-4'.

Я могу объединить массив со всеми числами в полную строку, но у меня возникают проблемы при объединении / объединении последовательных чисел.

Я попытался сравнить предыдущее и следующее значения с текущим значением в цикле с несколькими if -условиями, но я не мог найти правильные, чтобы он работал правильно.

Примеры:

if(ar[i-1] === ar[i]-1){}
if(ar[i+1] === ar[i]+1){}

Мой код выглядит так:

var ar = [1,2,3,4,7,8,9,13,16,17];

var pages = ar[0];
var lastValue = ar[0];

for(i=1; i < ar.length; i++){
      if(ar[i]-1 === lastValue){
          pages = pages + ' - ' + ar[i];
      }else{
          pages = pages + ', ' + ar[i];
      }
}

alert(pages);

Результат: 1 - 2, 3, 4, 7, 8, 9, 13, 16, 17

В конце все должно выглядеть так: 1-4, 7-9, 13, 16-17.


EDIT: Я использовал первый ответ по ссылке @CMS для моего скрипта. Похоже на более короткую версию фрагмента @ corschdi:

var ar = [1,2,3,4,7,8,9,13,16,17];


var getRanges = function(array) {
  var ranges = [], rstart, rend;
  for (var i = 0; i < array.length; i++) {
    rstart = array[i];
    rend = rstart;
    while (array[i + 1] - array[i] == 1) {
      rend = array[i + 1]; // increment the index if the numbers sequential
      i++;
    }
    ranges.push(rstart == rend ? rstart+'' : rstart + '-' + rend);
  }
  return ranges;
}


alert(getRanges(ar));

Ответы [ 2 ]

5 голосов
/ 16 мая 2019

В вашем коде lastValue никогда не изменяется в цикле, поэтому вы всегда будете сравнивать с первым элементом в массиве.Кроме того, когда вы находите совпадение, вы еще не готовы добавить результат pages - возможно, будет еще несколько цифр.

Одним из подходов может быть сохранение последовательности текущей последовательности чисел (или только первого и последнего чисел в серии) и добавление этой серии к строке результата только тогда, когда мы находим разрыв в последовательностиили нажмите конец строки.

Есть много способов подойти к этому, и я рекомендую проверять ответы других людей на Codewars: Range Extraction kata, который (почти) идентиченк этой проблеме.

Вот мое решение:

const rangeify = a => {
  const res = [];
  let run = []
  
  for (let i = 0; i < a.length; i++) {
    run.push(a[i]);

    if (i + 1 >= a.length || a[i+1] - a[i] > 1) {
      res.push(
        run.length > 1 ? `${run[0]}-${run.pop()}` : run
      );
      run = [];
    }
  }
  
  return res.join(", ");
};

[
  [1,2,3,4,7,8,9,13,16,17],
  [],
  [1],
  [1, 2],
  [1, 3],
  [1, 2, 3, 8],
  [1, 3, 4, 8],
  [1, 1, 1, 1, 2, 3, 4, 5, 5, 16],
  [-9, -8, -7, -3, -1, 0, 1, 2, 42]
].forEach(test => console.log(rangeify(test)));
1 голос
/ 16 мая 2019

Это должно работать:

var array = [1, 2, 3, 4, 7, 8, 9, 13, 16, 17];

var ranges = [];
var index = 0;
while (index < array.length) {
    var rangeStartIndex = index;
    while (array[index + 1] === array[index] + 1) {
        // continue until the range ends
        index++;
    }

    if (rangeStartIndex === index) {
        ranges.push(array[index]);
    } else {
        ranges.push(array[rangeStartIndex] + " - " + array[index]);
    }
    index++;
}

console.log(ranges.join(", "));
...