2016-01-14 2 views
-4

Я хочу, чтобы выбрать последовательные целые числа из массива, например:Выберите последовательные целые числа из массива в Ruby,

Input: (не должны быть отсортированы)

array = [1, 3, 6, 7, 8, 9, 10, 12, 13, 17] 

Ожидаемый результат:

#=> [6, 7, 8, 9, 10, 12, 13] 

Это мой код до сих пор:

array = [1, 3, 9, 6, 7, 10, 8, 12, 13, 17] 
newarray = [] 
z = 0 
array.sort.each_cons(2) do |x, y| 
    if y == x + 1 
    if z == 0 
     newarray.insert(0, x, y) 
    else 
     newarray.push(y) 
    end 
    end 
    z = z + 1 
end 

newarray #=> [7, 8, 9, 10, 13] 

Как видите, 6 и 12 отсутствуют.

Что не так с моим кодом и - помимо ошибки - есть ли лучший способ написать его?

+7

Существует сайт Stack биржи посвященного обзору коды, который может быть лучше спросить: HTTP : //codereview.stackexchange.com/ Вы также должны указать больше ввода и вывода примера и объяснить, что ваш код * предполагается * делать. Например. Правильный вывод для '[1,2,3,6,5]' должен быть '[1,2,3,6]' (т. Е. Он пропустит значение 5)? –

+0

Исправлен вопрос @NeilSlater –

+1

Пожалуйста, используйте английскую пунктуацию, когда вы пишете на английском языке. – sawa

ответ

5

Ваш код сравнивает соседние элементы x и y, но толкает x и y только если они являются первыми элементами в массиве (if z == 0; newarray.insert(0, x, y)). В противном случае нажимается только y, поэтому первый элемент каждой группы целых чисел отсутствует.

Эта таблица иллюстрирует то, что происходит:

x y y == x+1 
-------------------- 
    1 3 false 
    3 6 false 
    6 7 true  #=> push(7) 
    7 8 true  #=> push(8) 
    8 9 true  #=> push(9) 
    9 10 true  #=> push(10) 
10 12 false 
12 13 true  #=> push(13) 
13 17 false 

Вы можете исправить свой код, используя z в качестве индикатора для начала группы:

z = true 
array.sort.each_cons(2) do |x, y| 
    if y == x + 1 
    if z 
     newarray.push(x, y) 
     z = false 
    else 
     newarray.push(y) 
    end 
    else 
    z = true 
    end 
end 

Лучший способ заключается в использовании chunk_while , который был введен в Ruby 2.3:

array = [1, 3, 9, 6, 7, 10, 8, 12, 13, 17] 

array 
    .sort        #=> [1, 3, 6, 7, 8, 9, 10, 12, 13, 17] 
    .chunk_while { |x, y| y == x + 1 } #=> [[1], [3], [6, 7, 8, 9, 10], [12, 13], [17]] 
    .select { |a| a.size > 1 }   #=> [[6, 7, 8, 9, 10], [12, 13]] 
    .flatten       #=> [6, 7, 8, 9, 10, 12, 13] 

Вы заметили, что документация содержит аналогичный пример?

Например, один за одним, увеличивая подпоследовательности можно фрагментированный следующим образом:

a = [1,2,4,9,10,11,12,15,16,19,20,21] 
b = a.chunk_while {|i, j| i+1 == j } 
p b.to_a #=> [[1, 2], [4], [9, 10, 11, 12], [15, 16], [19, 20, 21]] 
Смежные вопросы