У меня есть несколько массивов с неизвестным количеством элементов, например
a = []
a << [:a, :c, :e]
a << [:b, :f, :g, :h, :i, :j]
a << [:d]
Результат должен быть что-то вроде ~ (мне все равно детали из-за округления и т. д.)
r = [:b, :a, :f, :g, :d, :c, :h, :i, :e, :j]
Вот как я думаю это можно сделать
Сначала нам нужно расширить / распределить одинаково элементы в каждом массиве на одинаковую длину, поэтому мы получаем что-то вроде
a << [nil, :a, nil, :c, nil, :e]
a << [:b, :f, :g, :h, :i, :j]
a << [nil, nil, :d, nil, nil]
Затем мы чередуем их, как обычно
r = a.shift
a.each { |e| r = r.zip(e) }
r = r.flatten.compact
Моя текущая проблема заключается в том, как равномерно (насколько это возможно) распределить эти элементы по массиву? Может быть один массив с 4 элементами, а другой с 5, но, вероятно, первым должен быть самый большой.
Конечно, было бы неплохо посмотреть, есть ли другой способ добиться этого :)
1 ответ
Я бы использовал для этого сортировку, основанную на позиции индекса элемента, разделенной на размер массива, плюс некоторое смещение на основе идентификатора массива, чтобы все было согласовано (если вам не нужна согласованность, вы можете вместо этого использовать небольшое случайное смещение ).
a = [:a,:b]
b = [:c]
c = [:d,:e,:f]
d = [:g:,:h,:i,:j]
def sort_pos array, id
(1..array.size).map { |i| (i - 0.5 + id/1000.0)/(array.size + 1e-6) }
end
# Combine all the arrays with their sort index, assigning ids to each array for consistency.
# Depending on how you receive these arrays, this structure can be built up programatically,
# as long as you add an array plus its sort index numbers at the same time
combined = (a + b + c + d).zip( sort_pos(a, 1) + sort_pos(b, 2) + sort_pos(c, 3) + sort_pos(d, 4) )
# Extract the values from the original arrays in their new order
combined.sort_by { |zipped| zipped[1] }.map { |zipped| zipped[0] }
=> [:g, :d, :a, :h, :e, :i, :b, :f, :j, :c]
В Ruby может быть более чистый способ сделать это. . . но я думаю, что конечный результат - это то, что вам нужно - «ровное» сочетание нескольких массивов.
Если вы заботитесь о равномерности смеси только со статистической точки зрения (т.е. со временем она «справедлива»), вы можете просто сделать это:
(a+b+c+d).shuffle
=> [:g, :b, :i, :c, :a, :h, :e, :j, :f, :d]
id
магия? без них вроде нормально работает :)
Похожие вопросы
Новые вопросы
ruby
Ruby - это многоплатформенный динамический объектно-ориентированный интерпретируемый язык с открытым исходным кодом. Тег [ruby] предназначен для вопросов, связанных с языком Ruby, включая его синтаксис и его библиотеки. Вопросы Ruby on Rails должны быть помечены [ruby-on-rails].
[nil, :a, nil, :c, nil, :e]
вместо[:a, :c, :e, nil, nil]
?