首页 文章

了解 Map 功能

提问于
浏览
231
map(function, iterable, ...)

将函数应用于iterable的每个项目并返回结果列表 . 如果传递了其他可迭代参数,则函数必须采用那么多参数,并且并行地应用于所有迭代的项 .

如果一个iterable比另一个短,则假定使用None项扩展 .

如果函数是 None ,则假定为identity函数;如果有多个参数, map() 将返回一个由包含所有迭代中相应项的元组组成的列表(一种转置操作) .

可迭代参数可以是序列或任何可迭代对象;结果始终是一个列表 .

这在制作笛卡尔积的过程中扮演什么角色?

content = map(tuple, array)

将元组放在哪里有什么影响?我还注意到,没有map函数,输出是 abc ,有了它,它就是 a, b, c .

我想完全理解这个功能 . 参考定义也很难理解 . 太多花哨的绒毛 .

6 回答

  • 29

    map 通过将函数应用于源的每个元素来创建新列表:

    xs = [1, 2, 3]
    
    # all of those are equivalent — the output is [2, 4, 6]
    # 1. map
    ys = map(lambda x: x * 2, xs)
    # 2. list comprehension
    ys = [x * 2 for x in xs]
    # 3. explicit loop
    ys = []
    for x in xs:
        ys.append(x * 2)
    

    n-ary map 相当于将输入迭代器压缩在一起,然后在该中间压缩列表的每个元素上应用转换函数 . 它不是笛卡尔积:

    xs = [1, 2, 3]
    ys = [2, 4, 6]
    
    def f(x, y):
        return (x * 2, y // 2)
    
    # output: [(2, 1), (4, 2), (6, 3)]
    # 1. map
    zs = map(f, xs, ys)
    # 2. list comp
    zs = [f(x, y) for x, y in zip(xs, ys)]
    # 3. explicit loop
    zs = []
    for x, y in zip(xs, ys):
        zs.append(f(x, y))
    

    我在这里使用了 zip ,但是当迭代次数不同时, map 行为实际上略有不同 - 正如其文档中所述,它将iterables扩展为包含 None .

  • 20

    Python3 - map(func,iterable)

    有一件事没有完全提到(虽然@BlooB有点提到它)是 Map 返回一个 Map 对象 NOT 一个列表 . 当涉及初始化和迭代的时间性能时,这是一个很大的区别 . 考虑这两个测试 .

    import time
    def test1(iterable):
        a = time.clock()
        map(str, iterable)
        a = time.clock() - a
    
        b = time.clock()
        [ str(x) for x in iterable ]
        b = time.clock() - b
    
        print(a,b)
    
    
    def test2(iterable):
        a = time.clock()
        [ x for x in map(str, iterable)]
        a = time.clock() - a
    
        b = time.clock()
        [ str(x) for x in iterable ]
        b = time.clock() - b
    
        print(a,b)
    
    
    test1(range(2000000))  # Prints ~1.7e-5s   ~8s
    test2(range(2000000))  # Prints ~9s        ~8s
    

    正如您所看到的,初始化map函数几乎不需要任何时间 . 但是,遍历map对象所需的时间比简单地遍历iterable要长 . 这意味着传递给map()的函数不会应用于每个元素,直到迭代中到达元素 . 如果你想要一个列表使用列表理解 . 如果你计划在for循环中迭代并在某个时刻中断,那么使用map .

  • 14

    map 根本不涉及笛卡尔积,虽然我想象精通函数式编程的人可能想出一些不可能理解的使用 map 生成一个的方法 .

    Python 3中的 map 等同于:

    def map(func, iterable):
        for i in iterable:
            yield func(i)
    

    并且Python 2的唯一区别在于它将构建一个完整的结果列表,以便一次性返回,而不是 yield ing .

    虽然Python约定通常更喜欢列表推导(或生成器表达式)来实现与调用 map 相同的结果,特别是如果您使用lambda表达式作为第一个参数:

    [func(i) for i in iterable]
    

    作为你在问题评论中所要求的一个例子 - “将一个字符串转换成一个数组”,通过'array'你可能想要一个元组或一个列表(它们都表现得像其他语言的数组一样) -

    >>> a = "hello, world"
     >>> list(a)
    ['h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd']
    >>> tuple(a)
    ('h', 'e', 'l', 'l', 'o', ',', ' ', 'w', 'o', 'r', 'l', 'd')
    

    如果你从字符串列表开始而不是单个字符串,那么 map 的使用就是这样 - map 可以单独地分解所有字符串:

    >>> a = ["foo", "bar", "baz"]
    >>> list(map(list, a))
    [['f', 'o', 'o'], ['b', 'a', 'r'], ['b', 'a', 'z']]
    

    请注意 map(list, a) 在Python 2中是等效的,但是在Python 3中,如果你想做任何其他事情而不是将它提供给 for 循环(或者只需要迭代而不是序列的处理函数,如 sum ),则需要 list 调用 . ) . 但同样请注意,列表理解通常是首选:

    >>> [list(b) for b in a]
    [['f', 'o', 'o'], ['b', 'a', 'r'], ['b', 'a', 'z']]
    
  • 2

    map 不是特别pythonic . 我建议使用列表推导代替:

    map(f, iterable)
    

    基本上相当于:

    [f(x) for x in iterable]
    

    map 本身不能做笛卡尔积,因为其输出列表的长度始终与其输入列表相同 . 你可以通过列表理解轻松地做一个笛卡尔积:

    [(a, b) for a in iterable_a for b in iterable_b]
    

    语法有点令人困惑 - 这基本上相当于:

    result = []
    for a in iterable_a:
        for b in iterable_b:
            result.append((a, b))
    
  • 77

    map() 函数用于对可迭代数据结构中的每个项应用相同的过程,如列表,生成器,字符串和其他内容 .

    让我们看一个例子: map() 可以迭代列表中的每个项目并将函数应用于每个项目,而不是返回(返回)新列表 .

    想象一下,你有一个带数字的函数,将该数字加1并返回:

    def add_one(num):
      new_num = num + 1
      return new_num
    

    您还有一个数字列表:

    my_list = [1, 3, 6, 7, 8, 10]
    

    如果要增加列表中的每个数字,可以执行以下操作:

    >>> map(add_one, my_list)
    [2, 4, 7, 8, 9, 11]
    

    注意:至少 map() 需要两个参数 . 首先是一个函数名,第二个是列表 .

    让我们看看 map() 可以做的其他一些很酷的事情 . map() 可以采用多个迭代(列表,字符串等),并将每个可迭代的元素作为参数传递给函数 .

    我们有三个清单:

    list_one = [1, 2, 3, 4, 5]
    list_two = [11, 12, 13, 14, 15]
    list_three = [21, 22, 23, 24, 25]
    

    map() 可以为您创建一个新列表在特定索引处包含元素的添加 .

    现在记住 map() ,需要一个功能 . 这次我们将使用内置的 sum() 函数 . 运行 map() 会得到以下结果:

    >>> map(sum, list_one, list_two, list_three)
    [33, 36, 39, 42, 45]
    

    REMEMBER:
    在Python 2 map() 中,将根据最长列表迭代(遍历列表的元素),并将 None 传递给较短列表的函数,因此您的函数应查找 None 并处理它们,否则您将收到错误 . 在Python 3中, map() 将在完成最短列表后停止 . 此外,在Python 3中, map() 返回迭代器,而不是列表 .

  • 327

    简化一下,你可以想象 map() 做这样的事情:

    def mymap(func, lst):
        result = []
        for e in lst:
            result.append(func(e))
        return result
    

    如您所见,它接受一个函数和一个列表,并返回一个新列表,其中包含将函数应用于输入列表中的每个元素的结果 . 我说"simplifying a bit"因为实际上 map() 可以处理多个迭代:

    如果传递了其他可迭代参数,则函数必须采用那么多参数,并且并行地应用于所有迭代的项 . 如果一个iterable比另一个短,则假定使用None项扩展 .

    对于问题的第二部分:这在制作笛卡尔积中起到了什么作用?好吧, map() 可用于生成列表的笛卡尔积,如下所示:

    lst = [1, 2, 3, 4, 5]
    
    from operator import add
    reduce(add, map(lambda i: map(lambda j: (i, j), lst), lst))
    

    ...但说实话,使用product()是解决问题的一种更简单自然的方法:

    from itertools import product
    list(product(lst, lst))
    

    无论哪种方式,结果都是 lst 的笛卡儿积,如上所述:

    [(1, 1), (1, 2), (1, 3), (1, 4), (1, 5),
     (2, 1), (2, 2), (2, 3), (2, 4), (2, 5),
     (3, 1), (3, 2), (3, 3), (3, 4), (3, 5),
     (4, 1), (4, 2), (4, 3), (4, 4), (4, 5),
     (5, 1), (5, 2), (5, 3), (5, 4), (5, 5)]
    

相关问题