Понимание списка во вложенном списке?
У меня есть этот вложенный список:
l = [['40', '20', '10', '30'], ['20', '20', '20', '20', '20', '30', '20'], ['30', '20', '30', '50', '10', '30', '20', '20', '20'], ['100', '100'], ['100', '100', '100', '100', '100'], ['100', '100', '100', '100']]
Теперь я хочу преобразовать каждый элемент списка в плавающее. Мое решение таково:
newList = []
for x in l:
for y in x:
newList.append(float(y))
Но можно ли это сделать с помощью понимания вложенного списка, верно?
что я сделал, это:
[float(y) for y in x for x in l]
Но тогда результат - куча 100 с суммой 2400.
Любое решение, объяснение будет высоко ценится. Спасибо!
Ответы
Ответ 1
Вот как вы могли бы сделать это с помощью вложенного списка:
[[float(y) for y in x] for x in l]
Это даст вам список списков, аналогичный тому, с чего вы начали, кроме как с поплавками вместо строк. Если вам нужен один плоский список, вы должны использовать [float(y) for x in l for y in x]
.
Ответ 2
Вот как конвертировать вложенный цикл в понимание вложенного списка:
![enter image description here]()
Вот как работает понимание вложенного списка:
l a b c d e f
↓ ↓ ↓ ↓ ↓ ↓ ↓
In [1]: l = [ [ [ [ [ [ 1 ] ] ] ] ] ]
In [2]: for a in l:
...: for b in a:
...: for c in b:
...: for d in c:
...: for e in d:
...: for f in e:
...: print(float(f))
...:
1.0
In [3]: [float(f)
for a in l
...: for b in a
...: for c in b
...: for d in c
...: for e in d
...: for f in e]
Out[3]: [1.0]
#Which can be written in single line as
In [4]: [float(f) for a in l for b in a for c in b for d in c for e in d for f in e]
Out[4]: [1.0]
Ответ 3
>>> l = [['40', '20', '10', '30'], ['20', '20', '20', '20', '20', '30', '20'], ['30', '20', '30', '50', '10', '30', '20', '20', '20'], ['100', '100'], ['100', '100', '100', '100', '100'], ['100', '100', '100', '100']]
>>> new_list = [float(x) for xs in l for x in xs]
>>> new_list
[40.0, 20.0, 10.0, 30.0, 20.0, 20.0, 20.0, 20.0, 20.0, 30.0, 20.0, 30.0, 20.0, 30.0, 50.0, 10.0, 30.0, 20.0, 20.0, 20.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0, 100.0]
Ответ 4
Не уверен, какой у вас желаемый результат, но если вы используете понимание списка, порядок следует за порядком вложенных циклов, который у вас есть назад. Поэтому я получил то, что, я думаю, хочу:
[float(y) for x in l for y in x]
Принцип: использовать тот же порядок, который вы использовали бы при написании его как вложенный для циклов.
Ответ 5
Поскольку я немного опоздал, но я хотел бы поделиться тем, как на самом деле работает понимание списков, особенно понимание вложенных списков:
New_list= [[float(y) for x in l]
фактически совпадает с:
New_list=[]
for x in l:
New_list.append(x)
А теперь понимание вложенного списка:
[[float(y) for y in x] for x in l]
такой же как;
new_list=[]
for x in l:
sub_list=[]
for y in x:
sub_list.append(float(y))
new_list.append(sub_list)
print(new_list)
выход:
[[40.0, 20.0, 10.0, 30.0], [20.0, 20.0, 20.0, 20.0, 20.0, 30.0, 20.0], [30.0, 20.0, 30.0, 50.0, 10.0, 30.0, 20.0, 20.0, 20.0], [100.0, 100.0], [100.0, 100.0, 100.0, 100.0, 100.0], [100.0, 100.0, 100.0, 100.0]]
Ответ 6
Если вам не нравятся вложенные списки, вы можете использовать функцию map,
>>> from pprint import pprint
>>> l = l = [['40', '20', '10', '30'], ['20', '20', '20', '20', '20', '30', '20'], ['30', '20', '30', '50', '10', '30', '20', '20', '20'], ['100', '100'], ['100', '100', '100', '100', '100'], ['100', '100', '100', '100']]
>>> pprint(l)
[['40', '20', '10', '30'],
['20', '20', '20', '20', '20', '30', '20'],
['30', '20', '30', '50', '10', '30', '20', '20', '20'],
['100', '100'],
['100', '100', '100', '100', '100'],
['100', '100', '100', '100']]
>>> float_l = [map(float, nested_list) for nested_list in l]
>>> pprint(float_l)
[[40.0, 20.0, 10.0, 30.0],
[20.0, 20.0, 20.0, 20.0, 20.0, 30.0, 20.0],
[30.0, 20.0, 30.0, 50.0, 10.0, 30.0, 20.0, 20.0, 20.0],
[100.0, 100.0],
[100.0, 100.0, 100.0, 100.0, 100.0],
[100.0, 100.0, 100.0, 100.0]]
Ответ 7
У меня была похожая проблема, чтобы решить, поэтому я столкнулся с этим вопросом. Я сделал сравнение производительности Эндрю Кларка и ответа Нараяна, которым я хотел бы поделиться.
Основное различие между двумя ответами заключается в том, как они перебирают внутренние списки. Один из них использует встроенную карту, в то время как другой использует понимание списка. Функция карты имеет небольшое преимущество в производительности по сравнению с аналогичным пониманием списка, если она не требует использования лямбда-выражения. Таким образом, в контексте этого вопроса map
должен работать немного лучше, чем понимание списка.
Давайте сделаем тест производительности, чтобы увидеть, правда ли это. Я использовал Python версии 3.5.0 для выполнения всех этих тестов. В первом наборе тестов я бы хотел, чтобы количество элементов в списке составляло 10, а количество списков варьировалось от 10 до 100 000.
>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*10]"
>>> 100000 loops, best of 3: 15.2 usec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*10]"
>>> 10000 loops, best of 3: 19.6 usec per loop
>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*100]"
>>> 100000 loops, best of 3: 15.2 usec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*100]"
>>> 10000 loops, best of 3: 19.6 usec per loop
>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*1000]"
>>> 1000 loops, best of 3: 1.43 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*1000]"
>>> 100 loops, best of 3: 1.91 msec per loop
>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*10000]"
>>> 100 loops, best of 3: 13.6 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*10000]"
>>> 10 loops, best of 3: 19.1 msec per loop
>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,10))]*100000]"
>>> 10 loops, best of 3: 164 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,10))]*100000]"
>>> 10 loops, best of 3: 216 msec per loop
![enter image description here]()
В следующем наборе тестов я хотел бы поднять количество элементов в списках до 100.
>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*10]"
>>> 10000 loops, best of 3: 110 usec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*10]"
>>> 10000 loops, best of 3: 151 usec per loop
>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*100]"
>>> 1000 loops, best of 3: 1.11 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*100]"
>>> 1000 loops, best of 3: 1.5 msec per loop
>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*1000]"
>>> 100 loops, best of 3: 11.2 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*1000]"
>>> 100 loops, best of 3: 16.7 msec per loop
>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*10000]"
>>> 10 loops, best of 3: 134 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*10000]"
>>> 10 loops, best of 3: 171 msec per loop
>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,100))]*100000]"
>>> 10 loops, best of 3: 1.32 sec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,100))]*100000]"
>>> 10 loops, best of 3: 1.7 sec per loop
![enter image description here]()
Давайте сделаем смелый шаг и изменим количество элементов в списках на 1000
>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*10]"
>>> 1000 loops, best of 3: 800 usec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*10]"
>>> 1000 loops, best of 3: 1.16 msec per loop
>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*100]"
>>> 100 loops, best of 3: 8.26 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*100]"
>>> 100 loops, best of 3: 11.7 msec per loop
>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*1000]"
>>> 10 loops, best of 3: 83.8 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*1000]"
>>> 10 loops, best of 3: 118 msec per loop
>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*10000]"
>>> 10 loops, best of 3: 868 msec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*10000]"
>>> 10 loops, best of 3: 1.23 sec per loop
>>> python -m timeit "[list(map(float,k)) for k in [list(range(0,1000))]*100000]"
>>> 10 loops, best of 3: 9.2 sec per loop
>>> python -m timeit "[[float(y) for y in x] for x in [list(range(0,1000))]*100000]"
>>> 10 loops, best of 3: 12.7 sec per loop
![enter image description here]()
Из этого теста мы можем сделать вывод, что map
имеет преимущество в производительности по сравнению с пониманием списка в этом случае. Это также применимо, если вы пытаетесь привести к int
или str
. Для небольшого числа списков с меньшим количеством элементов в списке разница незначительна. Для больших списков с большим количеством элементов в списке можно использовать map
вместо понимания списка, но это полностью зависит от потребностей приложения.
Однако я лично считаю, что понимание списка более читабельно и идиоматично, чем map
. Это де-факто стандарт в Python. Обычно люди более опытны и удобны (особенно новички) в использовании понимания списка, чем map
.
Ответ 8
Да, вы можете сделать это с помощью такого кода:
l = [[float(y) for y in x] for x in l]
Ответ 9
Эта проблема может быть решена без использования цикла for. Для этого будет достаточно однострочного кода. Здесь также будет работать Nested Map с лямбда-функцией.
l = [['40', '20', '10', '30'], ['20', '20', '20', '20', '20', '30', '20'], ['30', '20', '30', '50', '10', '30', '20', '20', '20'], ['100', '100'], ['100', '100', '100', '100', '100'], ['100', '100', '100', '100']]
map(lambda x:map(lambda y:float(y),x),l)
И Список вывода будет выглядеть следующим образом:
[[40.0, 20.0, 10.0, 30.0], [20.0, 20.0, 20.0, 20.0, 20.0, 30.0, 20.0], [30.0, 20.0, 30.0, 50.0, 10.0, 30.0, 20.0, 20.0, 20.0], [100.0, 100.0], [100.0, 100.0, 100.0, 100.0, 100.0], [100.0, 100.0, 100.0, 100.0]]
Ответ 10
Лучший способ сделать это, на мой взгляд, - использовать пакет python itertools
.
>>>import itertools
>>>l1 = [1,2,3]
>>>l2 = [10,20,30]
>>>[l*2 for l in itertools.chain(*[l1,l2])]
[2, 4, 6, 20, 40, 60]
Ответ 11
Да, вы можете сделать следующее.
[[float(y) for y in x] for x in l]
Ответ 12
deck = []
for rank in ranks:
for suit in suits:
deck.append(('%s%s')%(rank, suit))
Этого можно достичь с помощью понимания списка:
[deck.append((rank,suit)) for suit in suits for rank in ranks ]