#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)
, чтобы получить точное измерение массива, без заминок.