【问题标题】:Is there an in-place equivalent to 'map' in python?python中是否有与“地图”等效的原地?
【发布时间】:2011-05-08 02:18:40
【问题描述】:

我有一个需要清理的字符串列表。我有一种对它们进行消毒的方法,所以我可以这样做:

new_list = map(Sanitize, old_list)

但我不需要保留旧列表。这让我想知道是否有一个就地等效于 map 的方法。很容易为它编写一个 for 循环(或自定义的就地映射方法),但是有什么内置的吗?

【问题讨论】:

  • 是的,这是一个骗局。我发誓我搜索过是否已经有人问过这个问题。显然我的搜索技巧还不够好。 :)
  • 不是有意义的重复,因为没有回答该问题。老问题不太可能得到回答(没有办法“碰撞”问题),因此将其作为重复项关闭是没有意义的。像这样关闭骗子实际上会注定他们永远不会被回答。
  • @Glenn Maynard,投票结束,因为现在有了答案。
  • @aaronasterling:不,#3000461 中没有这个问题的答案。此问题已错误关闭。
  • 这仍然会创建一个新列表,但会重用 old_list old_list[:] = map(Sanitize, old_list)的引用

标签: python dictionary in-place


【解决方案1】:

最后,

old_list = map(Sanitize, old_list)

将完全按照您的需要完成。

你可能会反对创建一个新的列表对象和垃圾收集旧的比使用现有的慢。在实践中,这几乎永远不会成为问题(一次性分配一块内存不太可能成为瓶颈;也许如果您在循环中执行此操作或有一个很长的列表,您可以尝试进行基准测试,但我仍然会对你下注)。请记住,无论哪种方式,您都必须从头开始创建新字符串作为Sanitize 的一部分,这将更加昂贵。

值得注意的是,正如mluebke 所指出的,现在列表推导被认为比map 更“pythonic”(我相信map 在该语言的未来版本中已被弃用)。

编辑:啊,我看到您正在尝试编辑传递给函数的参数值。我相当强烈地认为这是“unpythonic”并且您应该将新列表作为您的返回值之一返回(请记住,使用元组您可以有多个返回值)。

【讨论】:

  • 就地位并不是真正的垃圾收集问题。问题是我在一些不返回结果的代码中插入了这种卫生。它只是改变了当前列表(列表中还有很多其他的东西也被修改了)。所以我需要改变它。
【解决方案2】:

答案很简单:不。

当答案为时,“XXX 是否存在”形式的问题永远不会直接得到回答,所以我想我会把它放在那里。

大多数 itertools 助手和内置函数都在通用迭代器上运行。 mapfilter、列表推导、for——它们都在迭代器上工作,而不是修改原始容器(如果有的话)。

为什么这个类别中没有任何变异函数?因为没有通用的、通用的方法来根据容器的键和值向容器分配值。例如,基本的 dict 迭代器 (for x in {}) 迭代键,并分配给 dict 使用 dict 的结果作为 [] 的参数。另一方面,列表遍历,并且赋值使用隐式索引。底层的一致性不能提供这样的通用函数,所以在itertools 或内置函数中没有这样的东西。

他们可以将其作为listdict 的方法提供,但目前还没有。你只需要自己动手。

【讨论】:

  • 粗略的网络搜索表明“XXX”确实存在,尽管它通常似乎与 Stack Overflow 无关。
  • @Jean-FrançoisCorbett 在 cmets 变得又热又重
【解决方案3】:

你必须循环:

for i in range(len(old_list)):
    old_list[i] = Sanitize(old_list[i])

没有内置任何东西。

如 cmets 中所建议:OP 所需的功能:

def map_in_place(fn, l):
    for i in range(len(l)):
        l[i] = fn(l[i])

map_in_place(Sanitize, old_list)

【讨论】:

  • 在你的 for 循环之前加上 def map_in_place(func, a_list):,我们有一个完整的答案。 (但old_list = map(Sanitize, old_list),虽然它不会改变旧列表,但似乎是最好的解决方案。)
【解决方案4】:

类似于使用this[0] = something,也可以指定切片:

>>> x = [1, 2, 3, 4]
>>> x[1:3] = [0, 0]
>>> x
[1, 0, 0, 4]

由于切片可以省略部分(开始、停止或步骤),您可以通过以下方式更改整个列表:

>>> x = [1, 2, 3, 4]
>>> x[:] = [4, 5, 6]
>>> x
[4, 5, 6]

这(如上所示)甚至可以改变列表的长度。如下图可见,这确实是在改变实际对象,而不是重新定义变量:

>>> x = [1, 2, 3, 4]
>>> y = x
>>> x[:] = [3, 4]
>>> y
[3, 4]

它不一定需要是作业右端的列表。任何可迭代的东西都可以在那边。事实上,你甚至可以拥有一个生成器:

>>> x = ["1", "2", "3", "4"]
>>> x[:] = (int(y) for y in x)
>>> x
[1, 2, 3, 4]

map() 的返回值(Python 2 中的列表;Python 3 中的 map 对象):

>>> x = ["1", "2", "3", "4"]
>>> x[:] = map(int, x)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-02-04
    • 2012-11-21
    • 2019-03-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-26
    • 1970-01-01
    相关资源
    最近更新 更多