Разделение массива с использованием each_with_slice, но с сохранением определенных значений в результирующих массивах (одна строка)

#arrays #ruby #slice #each

#массивы #ruby #срез #каждый

Вопрос:

Я надеюсь получить массив в определенном формате и сделать это в однострочном, если это возможно. Использование each_slice(2).to_a полезно при разделении массива, однако я хотел бы сохранить вторую координату каждого массива в качестве первой координаты следующего массива.

Исходный массив

 # format is [x1, y1, x2, y2, x3, y3, x4, y4]...

full_line_coords = [[1, 1, 2, 2, 3, 3, 4, 4], [5, 5, 6, 6, 7, 7, 8, 8]]
  

Желаемый результат

 # desired format is [[[x1, y1], [x2, y2]], [[x2, y2], [x3, y3]], [[x3, y3], [x4, y4]]]...
desired = [[[1, 1], [2, 2]], [[2, 2], [3, 3]], [[3, 3], [4, 4]]]
  

Успех без однострочного

 # without one line:

desired = []
temp_array = []

full_line_coords.each do |x|
  temp_array << x.each_slice(2).to_a
end

temp_array.each do |x|
  i = 0
  until i == x.length - 1
    desired << [x[i], x[i 1]]
    i  = 1
  end
end

p desired

# => [[[1, 1], [2, 2]], [[2, 2], [3, 3]], [[3, 3], [4, 4]], [[5, 5], [6, 6]], [[6, 6], [7, 7]], [[7, 7], [8, 8]]]
  

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

Однострочная попытка

 attempt = full_line_coords.each { |x| p x.each_slice(2).to_a.each_slice(2).to_a } # p to show this is where i'd like the array to be in 'desired' format if possible.

# => [[[1, 1], [2, 2]], [[3, 3], [4, 4]]]
#    [[[5, 5], [6, 6]], [[7, 7], [8, 8]]]
  

Предыстория / Рассуждения

Единственная причина, по которой я хочу сохранить его однострочным, заключается в том, что я хочу вернуть сам «родительский» объект, а не только результирующие атрибуты.

«Родительские» объекты, представляющие собой список ссылок: #<Link:0x803a2e8> , со многими атрибутами, включая «сегменты».

 links.each do |l|
  puts l.segments
end

# Gives an array of XY coordinates, including all vertices. e.g. [1, 1, 2, 2, 3, 3, 4, 4]
  

Затем я собираюсь использовать «желаемый» результат в некоторых других определенных методах, но возвращать сам объект ссылки в конце #<Link:0x803a2e8> , а не только продукты из атрибутов ссылки.

Большое спасибо.

Ответ №1:

Это первый вариант, который я нашел:

 full_line_coords.flat_map { |e| e.each_slice(2).each_cons(2).to_a } 
  

Найдите методы в классе Enumerable и классе Array

Комментарии:

1. Это идеально, большое спасибо — ранее не сталкивался с использованием each_cons !

Ответ №2:

Ввод

 full_line_coords = [[1, 1, 2, 2, 3, 3, 4, 4], [5, 5, 6, 6, 7, 7, 8, 8]]
  

Код

 p full_line_coords.map { |var| var.slice_when { |x, y| x != y }
                                   .each_cons(2)
                                   .to_enum
                                   .map(amp;:itself) }
  

Вывод

 [[[[1, 1], [2, 2]], [[2, 2], [3, 3]], [[3, 3], [4, 4]]], [[[5, 5], [6, 6]], [[6, 6], [7, 7]], [[7, 7], [8, 8]]]]
  

Комментарии:

1. Также работает хорошо, спасибо! Я добавил flatten(1) , чтобы получить точное измерение массива, без заминок.