Python 用map替换for循环

Python 用map替换for循环,python,Python,我试图用一个映射函数替换下面的for循环, 我假定它必须类似于MapinBeween,input.split\n,但当我执行此操作时,我的小时字典保持不变。我觉得它甚至没有进入功能 有人知道如何让它工作吗 #!/usr/local/bin/python3.5 input='''5 1 8 2 3 4 23 4 6 2 23''' hours = {} for time in range(1,25): hours[time] = 0 def inBetween(line): p

我试图用一个映射函数替换下面的for循环, 我假定它必须类似于MapinBeween,input.split\n,但当我执行此操作时,我的小时字典保持不变。我觉得它甚至没有进入功能

有人知道如何让它工作吗

#!/usr/local/bin/python3.5

input='''5
1 8
2 3
4 23
4 6
2 23'''

hours = {}
for time in range(1,25):
    hours[time] = 0
def inBetween(line):
    print(line)
    current = int(line.split(" ")[0])
    while current < int(line.split(" ")[1]):
        hours[current] +=1
        current += 1
for entree in range(1, int(input.split("\n")[0])+1):
        inBetween(input.split("\n")[entree])

print(hours)

正如WillemVanOnsem在评论中所说的,map在Python3中是懒惰的。与Python 2中的情况不同,map不会立即将函数应用于所有项并返回列表,而是返回一个生成器,您需要迭代该生成器才能实际执行转换:

>>> lst = [1, 2, 3]
>>> def square(x):
        print('Calculating square of', x)
        return x * x

>>> res = map(square, lst)
>>> res
<map object at 0x0000029C2E4B2CC0>
如果要返回列表,还可以调用结果上的列表,立即为每个元素调用函数:

>>> list(map(square, lst))
Calculating square of 1
Calculating square of 2
Calculating square of 3
[1, 4, 9]
不过请注意,您的案例并不真正适合map。从代码和输入中我可以看出,输入的第一行是一个数字,其中包含需要处理的行数

所以在您的情况下,除非您想主动忽略第一行,只处理每一行,否则不应该在这里使用map

但是,通过存储这些拆分调用的结果,可以使代码更简单、更高效。例如:

lines = input.split('\n')
for i in range(1, int(lines[0]) + 1):
    inBetween(lines[i])
在这里,您只是将输入拆分一次,而不是每次迭代拆分一次

对于中间函数,您也可以在此处使用for循环,这使它更简单:

def inBetween(line):
    # using a tuple unpacking to get both values from the line at once
    start, stop = line.split(' ') 
    for h in range(int(start), int(stop)):
        hours[h] += 1
最后,这里的中间函数实际上没有任何好处。由于它是对小时字典的全局状态的变异,因此它在其确切上下文之外并不真正有用,因此您可以在这里简单地内联功能。然后,您甚至可以提取逻辑,这样您就可以得到一个只处理输入并返回该字典的函数。与此相结合,实际上可以看起来非常漂亮:

from collections import defaultdict
def getHours(lines):
    hours = defaultdict(int)
    for i in range(1, int(lines[0]) + 1):
        start, stop = lines[i].split(' ')
        for h in range(int(start), int(stop)):
            hours[h] += 1
    return dict(hours)
这就是一切:

>>> getHours(input.split('\n'))
{ 1: 1,  2: 3,  3: 2,  4: 4,  5: 4,  6: 3,  7: 3,  8: 2,  9: 2, 10: 2,
 11: 2, 12: 2, 13: 2, 14: 2, 15: 2, 16: 2, 17: 2, 18: 2, 19: 2, 20: 2,
 21: 2, 22: 2 }

正如WillemVanOnsem在评论中所说的,map在Python3中是懒惰的。与Python 2中的情况不同,map不会立即将函数应用于所有项并返回列表,而是返回一个生成器,您需要迭代该生成器才能实际执行转换:

>>> lst = [1, 2, 3]
>>> def square(x):
        print('Calculating square of', x)
        return x * x

>>> res = map(square, lst)
>>> res
<map object at 0x0000029C2E4B2CC0>
如果要返回列表,还可以调用结果上的列表,立即为每个元素调用函数:

>>> list(map(square, lst))
Calculating square of 1
Calculating square of 2
Calculating square of 3
[1, 4, 9]
不过请注意,您的案例并不真正适合map。从代码和输入中我可以看出,输入的第一行是一个数字,其中包含需要处理的行数

所以在您的情况下,除非您想主动忽略第一行,只处理每一行,否则不应该在这里使用map

但是,通过存储这些拆分调用的结果,可以使代码更简单、更高效。例如:

lines = input.split('\n')
for i in range(1, int(lines[0]) + 1):
    inBetween(lines[i])
在这里,您只是将输入拆分一次,而不是每次迭代拆分一次

对于中间函数,您也可以在此处使用for循环,这使它更简单:

def inBetween(line):
    # using a tuple unpacking to get both values from the line at once
    start, stop = line.split(' ') 
    for h in range(int(start), int(stop)):
        hours[h] += 1
最后,这里的中间函数实际上没有任何好处。由于它是对小时字典的全局状态的变异,因此它在其确切上下文之外并不真正有用,因此您可以在这里简单地内联功能。然后,您甚至可以提取逻辑,这样您就可以得到一个只处理输入并返回该字典的函数。与此相结合,实际上可以看起来非常漂亮:

from collections import defaultdict
def getHours(lines):
    hours = defaultdict(int)
    for i in range(1, int(lines[0]) + 1):
        start, stop = lines[i].split(' ')
        for h in range(int(start), int(stop)):
            hours[h] += 1
    return dict(hours)
这就是一切:

>>> getHours(input.split('\n'))
{ 1: 1,  2: 3,  3: 2,  4: 4,  5: 4,  6: 3,  7: 3,  8: 2,  9: 2, 10: 2,
 11: 2, 12: 2, 13: 2, 14: 2, 15: 2, 16: 2, 17: 2, 18: 2, 19: 2, 20: 2,
 21: 2, 22: 2 }
这是因为python-3.x中的映射是惰性的,用listmap实现它。这是因为python-3.x中的映射是惰性的,用listmap实现它。。