我有一个从字符串拆分操作构建的列表,我想将它输入到map()函数,然后从它们的尾部括号和空格中删除这些子字符串。 并从他们重建一个列表。
teststring=" (A) / (B) "
result = list(map(str.strip, teststring.split("/"), " ()"))
但是最后,我只是简单地剥离了子串,而“所有组合都经过测试”,正如文档所述。
我知道另一种方法可用于列表理解:
result = [substr.strip(' ()' for substr in teststring.split("/")]
哪个有效..但我想知道为什么地图不能正常工作。
我在python 3.6.4上,在Windows64上安装了Anaconda 4.4。
附属问题;以下topic给出了一些查找函数源代码的指针。但我找不到地图的代码(通常是内置函数),所以我看不出它是否有错误...
答案 0 :(得分:4)
map
表现不像你想象的那样。 map
的第三个参数是不作为第一个参数提供的函数的参数。它被用作第二个迭代。
来自docs:
map(function,iterable,...)返回一个应用函数的迭代器 到每个可迭代的项目,产生结果。如果有的话 传递可迭代的参数,函数必须采用那么多参数 并且并行地应用于所有迭代的项目。同 多个迭代,迭代器在最短迭代时停止 累。对于已经安排了功能输入的情况 参数元组,参见itertools.starmap()
换句话说:
map(str.strip, teststring.split('/'), ' ()')
等同于
[substr.strip(' ()' for substr in teststring.split('/')]
。它远远等同于
[(substr_1.strip(), substr_2.strip()) for (substr_1, substr_2) in zip(teststring.split("/"), ' ()')]
看到区别?
答案 1 :(得分:3)
map
与您使用它的方式不同。当您执行map(f, a, b)
时,它会产生f(a[0], b[0]), f(a[1], b[1]), ...
,而您使用它时会产生f(a[0], b), f(a[1], b), ...
。
要解决此问题,您可以使用列表推导(如问题中)或lambda(例如lambda string: string.strip(" ()")
。
答案 2 :(得分:3)
问题是你似乎认为map
的最后一个参数作为参数传递给被映射的函数,而不是从文档中发生的事情:
map(func,* iterables) - >地图对象
创建一个迭代器,使用每个参数计算函数 迭代的。当最短的可迭代用尽时停止。
换句话说,list(map(f, [1,2,3], 'abc'))
相当于:
[f(1,'a'), f(2, 'b'), f(3, 'c')]
这不是你想要的。您希望使用string.strip
作为第二个参数部分应用 " ()"
,而是将" ()"
作为另一个可迭代的参数。所以,直截了当的解决方案,使用辅助函数:
In [9]: def strip_stuff(s):
...: return s.strip(" ()")
...:
In [10]: list(map(strip_stuff, teststring.split("/")))
Out[10]: ['A', 'B']
如果你需要灵活,你可以做一个因子功能:
In [12]: def make_strip(stuff):
...: def strip(s):
...: return s.strip(stuff)
...: return strip
...:
In [13]: list(map(make_strip(" ()"), teststring.split("/")))
Out[13]: ['A', 'B']
In [14]: list(map(make_strip("()"), teststring.split("/")))
Out[14]: [' (A) ', ' (B) ']
In [15]: list(map(make_strip(" )"), teststring.split("/")))
Out[15]: ['(A', '(B']
In [16]: list(map(make_strip(" ("), teststring.split("/")))
Out[16]: ['A)', 'B)']
答案 3 :(得分:3)
您可以使用operator.methodcaller
:
list(map(operator.methodcaller('strip',' ()'),teststring.split("/")))
答案 4 :(得分:1)
使用lambda
功能可以实现如下:
map(lambda s: s.strip(" ()"), teststring.split("/"))