The sum() function seems to be messing map objects

让人想犯罪 __ 提交于 2021-02-17 05:56:09

问题


I'm doing this code excercise for trying out functional programming in python, and I ran into problems with sum(), list(), and map objects. I don't understand what I'm doing wrong, but the list() function seems to be screwing with my map object.

This is the code I have:

people = [{'name': 'Mary', 'height': 160},
          {'name': 'Isla', 'height': 80},
          {'name': 'Sam'}]

heights = map(lambda x: x['height'], filter(lambda x: 'height' in x, people))

print(len(list(heights)))
print(sum(list(heights)))
print(len(list(heights)))

average_height = sum(list(heights)) / len(list(heights))
print(average_height)

heights should be a map object containing (or resulting in) a list of the two existing height entries: [160, 80].

printing the length should give 2, the sum of the two should obviously be 240, and the average should be 120.

The problem I'm facing, though, is that I get this error message:

2
0
0
Traceback (most recent call last):
  File "C:\Users\Hugo\Dropbox\Programmering\PythonProjekt\exercise2.py", line 12, in <module>
    average_height = sum(list(heights)) / len(list(heights))
ZeroDivisionError: division by zero

Yes, the length is right, but the sum is 0, and the second length print is 0 aswell. The whole zero-division fault must come from something there, and it seems that the list() function is causing it. Changing the print order still only lets through the first print statement correctly:

print(sum(list(heights)))
print(len(list(heights)))
print(len(list(heights)))

Gives:

240
0
0
Traceback (most recent call last):
  File "C:\Users\Hugo\Dropbox\Programmering\PythonProjekt\exercise2.py", line 12, in <module>
    average_height = sum(list(heights)) / len(list(heights))
ZeroDivisionError: division by zero

and removing the list() function:

print(sum(list(heights)))
print(len(heights))
print(len(list(heights)))

gives me:

240
Traceback (most recent call last):
  File "C:\Users\Hugo\Dropbox\Programmering\PythonProjekt\exercise2.py", line 9, in <module>
    print(len(heights))
TypeError: object of type 'map' has no len()

So I have no idea what's going on. The list() function should not be changing the map object in any way, right? And it stays a map object, but calling list() on it more than once seems to change its behaviour. I am confuse.


回答1:


Actually, calling list does change your map object. map is an iterator, not a data structure (in Python3). After it has been looped over once, it is exhausted. To reproduce the result, you need to recreate the map object.

In your case, what you probably want to do is create a list from the map to store the result, then perform the sum.

heights = list(heights)
average = sum(heights) / len(heights)

Edit: another approach.

You can calculate arithmetic mean (and other statistics) directly from iterators using the statistics module. Check out the docs.




回答2:


You can create a list by iterating over your map structure to avoid exhausting the iterator with every list call:

people = [{'name': 'Mary', 'height': 160},
      {'name': 'Isla', 'height': 80},
      {'name': 'Sam'}]

heights = [i for i in map(lambda x: x['height'], filter(lambda x: 'height' in x, people))]
average_height = sum(heights)/len(heights)

Output:

120.0


来源:https://stackoverflow.com/questions/47972274/the-sum-function-seems-to-be-messing-map-objects

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!