С этим кодом:

strs = ["111", "1000", "1000", "1000"]
# count the numbers of '0' and '1' respectively for each string in strs 
counts = map(lambda x: [x.count('0'), x.count('1')], strs)

cntSortBy0 = sorted(counts, key=lambda x: x[0])  # sort with counts of '0'

cntSortBy1 = sorted(counts, key=lambda x: x[1])  # sort with counts of '1'

Здесь у меня есть список strs со строками в качестве элементов.

Затем я подсчитываю числа '0' и '1' соответственно для каждой строки в strs и сохраняю результаты в counts (я сделал это с помощью map в python3, поэтому count является объектом карты).

После этого я впервые сортирую counts, и все работает нормально, но когда я сортирую counts во второй раз, он возвращает пустой список (cntSortBy1 пуст),

Я считаю, что это потому, что counts стал пустым после первой сортировки :

>>> strs = ["111", "1000", "1000", "1000"]
>>>  counts = map(lambda x: [x.count('0'), x.count('1')], strs)
>>> cntSortBy0 = sorted(counts, key=lambda x: x[0])  # sort with counts of '0'
>>> list(counts)
[]

Неудивительно, что cntSortBy1 пуст, но почему это происходит?

Кроме того, если я просто напечатаю list(counts), cntSortBy1 также станет пустым, как показано ниже,

>>> strs = ["111", "1000", "1000", "1000"]
>>> counts = map(lambda x: [x.count('0'), x.count('1')], strs)
>>> list(counts)
[[0, 3], [3, 1], [3, 1], [3, 1]]
>>> cntSortBy0 = sorted(counts, key=lambda x: x[0])
>>> cntSortBy0
[]
  • Означает ли это, что объект карты можно использовать только один раз, после чего он станет пустым списком?

  • Есть ли в Py3 другие объекты с такой же функцией? (Я пытался range(), это не так.)

Большое спасибо!!!

2
Yvonne 2 Май 2019 в 14:16

3 ответа

Лучший ответ

После того, как итератор исчерпан (то есть полностью перебран), повторять уже нечего, поэтому повторение во второй раз ничего не даст. Возьми этот пример.

a = map(int,['1','2','3'])

for i in a:
    print(i)

for i in a:
    print(i)

Это выведет:

1
2
3

Всякий раз, когда вам нужно перебрать итератор несколько раз, включите его в список (или другой тип последовательности):

a = list(map(int,['1','2','3']))

Это выводит:

1
2
3
1
2
3

При использовании sorted() вы также выполняете итерацию по объекту итератора map:

a = map(int,['1','2','3'])
print(sorted(a)) # output: [1, 2, 3]
print(sorted(a)) # output: []

a = list(map(int,['1','2','3']))
print(sorted(a)) # output: [1, 2, 3]
print(sorted(a)) # output: [1, 2, 3]
0
glhr 2 Май 2019 в 11:33

Согласно документам: https://docs.python.org/3/library /functions.html#map

карта (функция, повторяемая, ...)
Возвратите итератор, который применяет функцию к каждому элементу итерируемого, получая результаты.

Что карта делает, так это возвращает итератор, по которому вы можете итерировать, но как только вы закончите итерацию по ней, она становится пустой, или когда вы продолжаете итерацию по ней, размер итератора продолжает уменьшаться

Следовательно, когда вы закончили итерацию по итератору counts, возвращенному map(lambda x: [x.count('0'), x.count('1')], strs) через sorted(counts, key=lambda x: x[0]), он становится пустым

Чтобы избежать этого, вам нужно привести любой итератор, который вы хотите использовать повторно, в список, используя list(map(...)), и затем вы можете использовать его столько, сколько захотите, например.

In [1]:  strs = ["111", "1000", "1000", "1000"]                                                                                                                                                   

In [2]: counts = list(map(lambda x: [x.count('0'), x.count('1')], strs))                                                                                                                          

In [3]: counts)                                                                                                                                                                             
Out[3]: [[0, 3], [3, 1], [3, 1], [3, 1]]

In [4]: cntSortBy0 = sorted(counts, key=lambda x: x[0])                                                                                                                                           

In [5]: cntSortBy0                                                                                                                                                                                
Out[5]: [[0, 3], [3, 1], [3, 1], [3, 1]]

In [6]: counts                                                                                                                                                                                    
Out[6]: [[0, 3], [3, 1], [3, 1], [3, 1]]

In [7]: cntSortBy1 = sorted(counts, key=lambda x: x[1])                                                                                                                                           

In [9]: cntSortBy1                                                                                                                                                                                
Out[9]: [[3, 1], [3, 1], [3, 1], [0, 3]]

In [10]: counts                                                                                                                                                                                   
Out[10]: [[0, 3], [3, 1], [3, 1], [3, 1]]

Как видите, мы использовали counts дважды, но это никогда не было пустыми, поскольку теперь мы преобразовали его в список, который не поврежден даже после того, как вы выполняете итерацию в течение бесчисленного количества раз.

0
Devesh Kumar Singh 2 Май 2019 в 12:09

В Python3 map возвращает итератор: https://docs.python.org/3/library/functions.html# карта

Итераторы могут (и должны) использоваться только один раз. Смотрите официальный документ об итераторах: https://docs.python.org/3/tutorial/classes.html# итераторы

В вашем случае вам нужно преобразовать map в list при создании, это решит вашу проблему:

counts = list(map(lambda x: [x.count('0'), x.count('1')], strs))
2
aikikode 2 Май 2019 в 11:21