Является ли объект итератора карты в Python3.x может использоваться только один раз и почему?(коды и примеры прилагаются) - PullRequest
2 голосов
/ 02 мая 2019

С этим кодом:

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 (я сделал это, используя карту в 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(), это не так.)

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

Ответы [ 3 ]

2 голосов
/ 02 мая 2019

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

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

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

counts = list(map(lambda x: [x.count('0'), x.count('1')], strs))
0 голосов
/ 02 мая 2019

По документам: 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 голосов
/ 02 мая 2019

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

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]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...