Как мне суммировать массив целых чисел как массив диапазонов? - PullRequest
9 голосов
/ 24 декабря 2011

Я хотел бы взять ввод, такой как:

[1,2,4,5,6,7,9,13]

и превратить его во что-то вроде следующего:

[[1,2],[4,7],[9,9],[13,13]]

Каждый под-массив представляет диапазон целых чисел.

Ответы [ 5 ]

21 голосов
/ 24 декабря 2011

Функциональный подход с использованием Enumerable # chunk :

ranges = [1, 2, 4, 5, 6, 7, 9, 13]
  .enum_for(:chunk) # .chunk for Ruby >= 2.4
  .with_index { |x, idx| x - idx }
  .map { |_diff, group| [group.first, group.last] }

#=> [[1, 2], [4, 7], [9, 9], [13, 13]]

Как это работает: после индексации последовательные элементы в массиве имеют одинаковое x - idx, поэтому мы используем это значение длячанк (группировка последовательных элементов) входного массива.Наконец, нам просто нужно взять первый и последний элементы каждой группы для построения пар.

5 голосов
/ 24 декабря 2011

Это почти прямо из перечисляемой перечисляемой # slice_before документации по методу:

ar = [1,2,4,5,6,7,9,13]
prev = ar[0]
ar.slice_before{|e|prev,prev2 = e,prev; prev2.succ != e}.map{|a|a.first..a.last}
#=> [1..2, 4..7, 9..9, 13..13]

Это должно работать с символами, датами и всем, что связано с методом .succ.

4 голосов
/ 06 октября 2016

Еще более простое решение, чем @ tokland. использует chunk_while:

xs.chunk_while { |a, b| a + 1 == b }.map do |seq|
  [seq.first, seq.last]
end

Примечание : chunk_while был представлен в Ruby 2.3

3 голосов
/ 24 декабря 2011

Хм, ну, это не шедевр Tokland , но я думаю, что это может быть хорошим простым решением ...

[1,2,4,5,6,7,9,13].inject([]) do |m, v|
  if m.last.to_a.last == v.pred
    m[-1][-1] = v
  else
    m << [v, v]
  end
  m
end
0 голосов
/ 24 декабря 2011

Другой подход

def summarize(x)
  x.inject([]) do |acc, value|
    if acc.last && acc.last[1] + 1 == value
      acc.last[1] = value
      acc
    else
      acc << [value,value]
    end
  end
end

Аналогичен методу Ларсенала, но использует inject для управления скучными вещами.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...