理解地图功能

2024-12-16 08:35:00
admin
原创
130
摘要:问题描述:Python 2 文档说:内置函数:map(function, iterable, ...)将函数应用于可迭代对象的每个项并返回结果列表。如果传递了其他可迭代对象参数,函数必须接受那么多参数并并行应用于所有可迭代对象的项。如果一个可迭代对象比另一个可迭代对象短,则假定它用 None 项进行扩展。如果...

问题描述:

Python 2 文档说:

内置函数:map(function, iterable, ...)

将函数应用于可迭代对象的每个项并返回结果列表。如果传递了其他可迭代对象参数,函数必须接受那么多参数并并行应用于所有可迭代对象的项。

如果一个可迭代对象比另一个可迭代对象短,则假定它用 None 项进行扩展。

如果函数为None,则假定为恒等函数;如果有多个参数,map()则返回由包含所有可迭代对象的相应项的元组组成的列表(一种转置运算)。

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

这对于制作笛卡尔积起什么作用?

content = map(tuple, array)

将元组放在其中的任何地方会有什么影响?我还注意到,如果没有 map 函数,输出为 ,abc而有了它,输出为a, b, c

我想完全理解这个函数。参考定义也很难理解。太多花哨的东西了。


解决方案 1:

map不是特别符合 Python 风格。我建议改用列表推导式:

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))

解决方案 2:

map与笛卡尔积完全不相关,尽管我认为精通函数式编程的人可能会想出一些难以理解的方法来使用 生成一个map

map在 Python 3 中相当于:

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

而在 Python 2 中唯一的区别是它将建立一个完整的结果列表并一次性返回,而不是yielding。

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

[func(i) for i in iterable]

作为您在问题评论中要求的一个例子 - “将字符串变成数组”,通过'数组',您可能需要一个元组或一个列表(它们的行为有点像其他语言中的数组) -

 >>> 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 中,list如果你想做除了将其输入循环之外的任何事情,则需要调用for(或者诸如只需要可迭代而不是序列的处理函数sum)。但还要注意,通常首选列表推导:

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

解决方案 3:

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-arymap相当于将输入的可迭代对象压缩在一起,然后将转换函数应用于中间压缩列表的每个元素。它不是笛卡尔积:

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可迭代对象的大小不一样时,行为实际上略有不同 - 如其文档中所述,它扩展了可迭代对象以包含None

解决方案 4:

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

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

如您所见,它接受一个函数和一个列表,并返回一个新列表,该列表是将函数应用于输入列表中的每个元素的结果。我说“简化一点”,因为实际上map()可以处理多个可迭代对象:

如果传递了额外的可迭代参数,函数必须接受那么多参数,并并行应用于所有可迭代项。如果一个可迭代项比另一个短,则假定使用 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)]

解决方案 5:

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]

记住:

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

解决方案 6:

Python3 - map(函数,可迭代)

有一件事没有完全提到(尽管@BlooB 提到了这一点),那就是 map 返回一个 map 对象而不是列表。当涉及到初始化和迭代的时间性能时,这是一个很大的区别。考虑这两个测试。

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 对象比简单地遍历可迭代对象花费的时间更长。这意味着传递给 map() 的函数在迭代中到达元素之前不会应用于每个元素。如果您想要一个列表,请使用列表推导。如果您计划在 for 循环中进行迭代并且会在某个时候中断,那么请使用 map。

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2545  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1551  
  建筑工程全生命周期涉及从项目规划、设计、施工到运营维护等多个复杂阶段,每个阶段都产生和依赖大量信息。PLM(产品生命周期管理)系统作为一种整合数据、流程和人员的数字化解决方案,正逐渐成为建筑行业实现高效协同与可持续发展的关键支撑。通过数字化转型,PLM系统能够优化各阶段的工作流程,提升项目整体质量和效率,为建筑工程的全...
plm是什么软件   1  
  产品生命周期管理(PLM)系统在企业资源成本率优化方面发挥着至关重要的作用。通过构建有效的数据模型,PLM系统能够整合企业各个环节的数据,为资源成本的精准分析和优化提供有力支持。这不仅有助于企业降低成本,还能提升产品质量和市场竞争力。PLM系统概述PLM系统是一种用于管理产品从概念设计到退役全生命周期过程中所有信息和流...
PLM项目管理软件   1  
  产品生命周期管理(PLM)系统在现代企业的产品研发、生产与管理过程中扮演着至关重要的角色。它整合了从产品概念设计到产品退役的全生命周期数据与流程,助力企业提升效率、降低成本并增强创新能力。随着技术的不断发展,到 2025 年,PLM 系统将具备一系列核心功能模块,这些模块将深度影响企业的运营与发展。产品数据管理模块产品...
plm是什么意思   0  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用