Вот один из способов интерпретации гомогенного смешивания: предположим, что два списка имеют длины m и n (соответственно). Поместите элементы первого списка в подинтервальд [0, 1) реальной линии, равномерно распределенные между ними с промежутком в 1/м. Поэтому мы могли бы разместить эти элементы в положениях 0/m, 1/m, 2/m, ... (m-1)/m. Но есть место для маневра: мы могли бы также разместить элементы в положениях x/m, (x + 1)/m, (x + 2)/m, ... для любого x в диапазоне [0, 1). Сделайте то же самое для элементов второго списка, разместив их на расстоянии 1/n друг от друга, чтобы все элементы снова содержались в [0, 1). Теперь, чтобы получить однородное сочетание двух списков, прочитайте все элементы (из обоих списков) точно так, чтобы они отображались вдоль реальной строки. Если размещение таково, что элементы из первого и второго списка точно совпадают в одной или нескольких точках, отдавайте предпочтение первому списку (скажем) каждый раз, когда это происходит.
Вы можете запрограммировать эту идею относительно легко, и после небольшого упрощения вы закончите что-то довольно короткое и элегантное. Вот функциональный генератор, который генерирует последовательные элементы смешанного списка:
def mix_lists(l1, l2):
""" Mix two lists evenly, generating the elements of the mixed list. """
m, n = len(l1), len(l2)
for i in range(m + n):
q, r = divmod(i * n, m + n)
yield l1[i - q] if r < m else l2[q]
Это соответствует случаю, когда мы поместили элементы первого списка, насколько влево, насколько это возможно в пределах [0, 1), т.е. на 0/m, 1/m, ..., а элементы второго списка близки к крайнему правому возможному положению (поэтому первый элемент близок к 1/n, второй - к 2/n и т. д.). Таким образом, внутри свобода, которую мы имеем, элементы первого списка имеют тенденцию появляться раньше, чем элементы второго.
Вот пример работы в случае, когда один список имеет длину кратен другой:
>>> list(mix_lists('abcdef', [1, 2, 3]))
['a', 'b', 1, 'c', 'd', 2, 'e', 'f', 3]
И пару примеров, когда это не так:
>>> list(mix_lists('abcdefgh', range(12)))
['a', 0, 'b', 1, 2, 'c', 3, 'd', 4, 5, 'e', 6, 'f', 7, 8, 'g', 9, 'h', 10, 11]
>>> list(mix_lists('abcdefg', [1, 2, 3, 4]))
['a', 'b', 1, 'c', 'd', 2, 'e', 'f', 3, 'g', 4]
Теперь немного вариации, вы можете добавить смещение в вызове divmod
: это смещение должно быть строго в диапазоне 0 <= offset < m + n
. Регулировка смещения означает смещение элементов одного или другого списка (но с ограничениями, спрятанными так, чтобы все элементы все еще лежали в интервале [0, 1)). Изменяя смещение, мы получаем все возможные «равномерно смешанные» шаблоны.
def mix_lists(l1, l2, offset=0):
""" Mix two lists evenly, generating the elements of the mixed list. """
m, n = len(l1), len(l2)
for i in range(m + n):
q, r = divmod(i * n + offset, m + n)
yield l1[i - q] if r < m else l2[q]
Вот несколько примеров различий в смешении при смещении.
>>> list(mix_lists('abcdefg', [1, 2, 3, 4], offset=0))
['a', 'b', 1, 'c', 'd', 2, 'e', 'f', 3, 'g', 4]
>>> list(mix_lists('abcdefg', [1, 2, 3, 4], offset=2))
['a', 'b', 1, 'c', 2, 'd', 'e', 3, 'f', 'g', 4]
>>> list(mix_lists('abcdefg', [1, 2, 3, 4], offset=5))
['a', 1, 'b', 'c', 2, 'd', 3, 'e', 'f', 4, 'g']
>>> list(mix_lists('abcdefg', [1, 2, 3, 4], offset=9))
[1, 'a', 'b', 2, 'c', 3, 'd', 'e', 4, 'f', 'g']
>>> mix_lists('abcdefg', [1, 2, 3, 4], offset=10)
[1, 'a', 2, 'b', 'c', 3, 'd', 'e', 4, 'f', 'g']
Выбор максимального смещение т + п - 1 результаты во втором списке будучи предпочитать первый, при выборе смещения вокруг (т + п)/2 будет означать, что мы начинаем с элементами из длинный список, который особенно хорошо работает в том случае, если один список ровно один элемент больше, чем другие:
>>> list(mix_lists('abcd', [1, 2, 3]))
['a', 'b', 1, 'c', 2, 'd', 3]
>>> list(mix_lists('abcd', [1, 2, 3], offset=3))
['a', 1, 'b', 2, 'c', 3, 'd']
>>> list(mix_lists('abcd', [1, 2, 3], offset=6))
[1, 'a', 2, 'b', 3, 'c', 'd']
Когда 'len (b)/len (a)' не является целым числом, как вы хотите смешать списки? Кроме того, если вы все пробовали что-либо, вы должны опубликовать это также. –
Как насчет фрагмента более длинного списка на две части? Смешайте первую часть с другим списком и добавьте вторую (несмешанную) часть в смешанный список. – albert
что должно быть 'a = [1, 2, 3, 4]; b = ['a', 'b', 'c', 'd', 'e', 'f']' output? –