#python #list #indexing #merge
Вопрос:
Я хочу объединить вложенный список (списки в нем имеют разную длину) в один. Я хотел бы сначала добавить по индексу. Затем отсортируйте по размеру.
Пример:
lsts = [
[7, 23, 5, 2],
[3, 8, 1],
[99, 23, 9, 23, 74]
]
merged = [3, 7, 99, 8, 23, 23, 1, 5, 9, 2, 23, 74]
Я хотел бы решить эту проблему без импорта.
Комментарии:
1. Вы пробовали написать цикл над индексами и использовать
sorted
функцию?
Ответ №1:
Предполагая, что ваш список списков не может содержать None
s, вы можете сделать это с помощью itertools.zip_longest
:
from itertools import zip_longest
result = []
for row in zip_longest(*lsts):
row = (x for x in row if x is not None)
for x in sorted(row):
result.append(x)
print(result)
Комментарии:
1. Большое спасибо, но я хотел бы решить эту проблему без импорта. Я также отметил это в своем посте сейчас.
2. Почему бы не импортировать набор стандартных инструментов, которые, скорее всего, будут гораздо более производительными, чем ручной код wirtten? Возможно, это упражнение по кодированию или школьное задание? В противном случае я не вижу веской причины не использовать импорт стандартных библиотек.
3. Действительно, это задача, в первую очередь направленная на понимание логики. Но я уже давно не ходил в школу :’)
4. FWIW, в документах для itertools.zip_longest() приведен эквивалент кода на Python, который не использует импорт. То же самое для itertools.chain() . Вы можете использовать это для создания решения, фактически ничего не импортируя. 🙂
Ответ №2:
Вот однострочный:
import functools
import itertools
functools.reduce(lambda x,y: x y, [sorted(x for x in p if x is not None) for p in itertools.zip_longest(*lsts)])
Выход:
[3, 7, 99, 8, 23, 23, 1, 5, 9, 2, 23, 74]
Комментарии:
1. Большое спасибо, но я хотел бы решить эту проблему без импорта. Я также отметил это в своем посте сейчас.
2. @red_joice Если вы хотите решить эту проблему без импорта, то это звучит как домашнее задание, которое вы должны попытаться решить самостоятельно. Что вы пробовали? Где ты застрял?
Ответ №3:
Я объясню решение шаг за шагом с каждым построением на результатах предыдущего шага.
Чтобы сгруппировать элементы из каждого списка по их индексам, itertools.zip_longest() является инструментом для этого:
>>> import itertools as it
>>> MISSING = object() # a sentinel
>>> lsts = [
[7, 23, 5, 2],
[3, 8, 1],
[99, 23, 9, 23, 74]
]
>>> it.zip_longest(*lsts, fillvalue=MISSING)
>>> list(_)
[(7, 3, 99), (23, 8, 23), (5, 1, 9), (2, <object object at 0x7f529e9b4260>, 23), (<object object at 0x7f529e9b4260>, <object object at 0x7f529e9b4260>, 74)]
Это группирует элементы списка в n-кортежей, используя при необходимости ОТСУТСТВУЮЩЕЕ значение заполнения, поскольку списки могут быть разной длины.
Следующий шаг-выполнить итерацию по каждому n-кортежу и отсортировать его внутри (пропуская ПРОПУЩЕННЫЕ значения). Встроенная функция sorted() пригодится здесь:
>>> list(
sorted(x for x in ntuple if x is not MISSING)
for ntuple in it.zip_longest(*lsts, fillvalue=MISSING)
)
[[3, 7, 99], [8, 23, 23], [1, 5, 9], [2, 23], [74]]
Последний шаг-сгладить эту последовательность списков, и мы будем использовать itertools.chain,from_iterable():
>>> list(it.chain.from_iterable(
sorted(x for x in ntuple if x is not MISSING)
for ntuple in it.zip_longest(*lsts, fillvalue=MISSING)
))
[3, 7, 99, 8, 23, 23, 1, 5, 9, 2, 23, 74]
Хорошая вещь в том chain.from_iterable()
, что он не многократно объединяет меньшие списки в более длинный и длинный окончательный список, что делает его эффективным. Он также делает это на уровне C, AFAIK.
Стоит отметить, что None
это также можно использовать вместо MISSING
sentinel, но я использовал MISSING, чтобы также продемонстрировать, как fillvalue
это работает (например, вы можете использовать вместо нуля или что-то другое, если хотите).
Ответ №4:
zip_longest делает свою работу. Остальное-очистка/форматирование
In [1]: from itertools import zip_longest, chain
In [2]: lsts = [
...: [7, 23, 5, 2],
...: [3, 8, 1],
...: [99, 23, 9, 23, 74]
...: ]
In [3]: [v for v in chain.from_iterable(zip_longest(*lsts)) if v !=None]
Out[3]: [7, 3, 99, 23, 8, 23, 5, 1, 9, 2, 23, 74]