简体   繁体   English

为什么Python 3中的map对象需要转换为列表才能具有理解功能?

[英]Why does the map object in Python 3 need to be cast to a list to function with comprehension?

This question comes from a hackerrank question from basic data types. 这个问题来自基本数据类型的hackerrank问题。 When I run 当我跑步

max(map(int, range(5)))

I get the right output of 4, however when I do 我得到正确的输出4,但是当我这样做时

if __name__ == '__main__':
    n = int(input()) #this line seems irrelevant to my question, but it was present in the original question so I have included it here for completeness
    arr = map(int, input().split())
    print(max([x for x in arr if x < max(arr)]))

and give input 并输入

5
2 3 6 6 5

the result is 2. However if I first cast the map object to a list I get the correct answer of 5. This is further bewildering as when I replace the print argument with 结果是2。但是,如果我首先将map对象转换为列表,则会得到正确的答案5。这进一步令人困惑,因为当我将print参数替换为

print(max(arr))

it gives the correct answer of 6, so clearly max works, but I'm guessing something in the list comprehension breaks on map objects for some reason. 它给出正确的答案6,因此max显然很有效,但是由于某种原因,我猜测列表对象中的某些理解会中断。 This is especially supported by the fact that if I do 如果我这样做,这一点尤其得到支持

print([x for x in arr if x < max(arr)])

I get 2. More testing with other less ordered lists shows that the last statement seems to always return list(arr)[0], so ultimately I expect the issue is with the list comprehension on the map objects. 我得到2。使用其他排序较少的列表进行的更多测试表明,最后一条语句似乎总是返回list(arr)[0],因此最终我希望问题出在对地图对象的列表理解上。 So ultimately what I'd like to know is 所以最终我想知道的是

  • How does Python 3.5.x deal with map objects and list comprehensions which is causing the failure? Python 3.5.x如何处理导致失败的地图对象和列表推导?
  • Is there any way to successfully process the map object in a straightforward way with a comprehension that does not involve casting? 有什么方法可以以不涉及转换的理解直接地成功处理地图对象?

The return value of map in Python 3 is not a list, but an iterable object. Python 3中map的返回值不是列表,而是一个可迭代的对象。 It can easily be turned into a list, but if you use it directly, it can't be iterated multiple times. 可以轻松地将其转换为列表,但是如果直接使用它,则不能多次迭代。 If you iterate it once in order for max to be calculated, you have used it up, and you won't get all the items again. 如果对它进行一次迭代以便计算出max ,则说明它已经用完,并且不会再得到所有项目。

In Python 2, map built a list for you, so you didn't get the option of lazily evaluating the items inside it. 在Python 2中, map为您构建了一个列表,因此您没有选择延迟评估其中的项目。 In Python 3, you can pass it to the list function to get a list. 在Python 3中,您可以将其传递给list函数以获取列表。

In Python 3, map gives you an iterator . 在Python 3中, map提供了一个迭代器 So arr gives you the numbers 2, 3, 6, 6 and 5 once . 所以arr为您提供了数字2,3,6,6和5 When you do [x for x in arr if x < max(arr)])) , the for x in arr asks arr for its next element, which is 2 , and assigns that to x . 当你[x for x in arr if x < max(arr)]))for x in arr要求arr为它的下一个元件,它是2 ,并且分配该至x Then the max(arr) goes over the remaining numbers (3, 6, 6 and 5) and returns the maximum, which is 6 . 然后, max(arr)遍历其余的数字max(arr)和5)并返回最大值,即6 Since 2 is less than 6 , it ends up in your result. 由于2小于6 ,因此最终得到结果。 Then the for x in arr goes again, and since arr already went through everything, we're finished. 然后for x in arrfor x in arr再次出现,由于arr已经经历了所有事情,所以我们完成了。 So that's why your result is [2] . 这就是为什么您的结果是[2]

You're wrong about the list always containing the first element, though. 但是,您对于总是包含第一个元素的列表是错误的。 If you for example enter 4 3 2 1 , then the resulting list is empty (because 4 isn't less than the maximum of 3, 2 and 1). 例如,如果输入4 3 2 1 ,则结果列表为 (因为4不小于3、2和1的最大值)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM