Как сжать массивы целых чисел в массив диапазонов и целых чисел в Ruby - PullRequest
1 голос
/ 28 апреля 2020

У меня есть отсортированный массив целых чисел, и я хочу, чтобы все подмножества последовательных целых чисел были заменены диапазоном, так что:

[1,2,3,4,5,6,7,8,9,10,42]

заменяется на:

[1..10,42]

Это список строк из электронной таблицы Google, которые пользователь ввел неправильно, и которые нельзя импортировать в базу данных другой системы. Есть много рядов, и часто десятки в последовательности. Пользователю гораздо проще увидеть, что строки 3201-3379 все плохие, чем читать каждое число строк по отдельности.

Я не прошу " Массив целых чисел в массив диапазоны".

Я знаю, как написать код, и я рад это сделать, но нет, если кто-то уже это сделал. Мой текущий код не элегантен, и я не буду беспокоиться о его рефакторинге, если что-то уже хорошо протестировано и оптимизировано.

1 Ответ

6 голосов
/ 28 апреля 2020

Я ожидаю, что этот вопрос был задан в SO, но ответ не в моем Rolodesk. Однако сделать это достаточно просто.

arr = [1, 2, 3, 5, 6, 7, 8, 10, 12, 13, 14, 17, 18, 20]

arr.slice_when { |x,y| y > x+1 }.
    map { |a| a.size == 1 ? a.first : a.first..a.last }
  #=> [1..3, 5..8, 10, 12..14, 17..18, 20]

См. Enumerable # slice_when .

Сначала мы вычислим перечислитель

enum = arr.slice_when { |x,y| y > x+1 }
  #=> #<Enumerator: #<Enumerator::Generator:0x...0000...fe0>:each>

Мы можем преобразовать enum в массив, чтобы увидеть элементы, которые будут сгенерированы перечислителем и переданы в map:

enum.to_a
  #=> [[1, 2, 3], [5, 6, 7, 8], [10], [12, 13, 14], [17, 18], [20]]

В качестве упражнения посмотрите, есть ли еще Enumerable метод, который вы могли бы использовать вместо slice_when. (Подсказка: рассмотрите Великие Дебаты Арахисового масла .)

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