python map / reduce:从单个映射lambda中发出多个键值

时间:2016-05-31 12:58:49

标签: python python-2.7

是否有规范的方法从输入序列中的单个项目发出多个键,以便它们形成连续的序列,我不需要使用reduce(...)来平整序列?

e.g。如果我想将一系列数字中的每个数字扩展为一个序列中的单个数字

[1,12,123,1234,12345] => [1,1,2,1,2,3,1,2,3,4,1,2,3,4,5]

然后我会写一些看起来有点像这样的python:

somedata = [1,12,123,1234,12345]

listified = map(lambda x:[int(c) for c in str(x)], somedata)
flattened = reduce(lambda x,y: x+y,listified,[])

但如果有更简洁(或更有效)的表达方式,我宁愿不要调用flattened = reduce(...)

2 个答案:

答案 0 :(得分:3)

map(func, *iterables)将始终将func调用为最短迭代次数的长度(假设没有引发异常)。函数始终返回单个对象。因此list(map(func, *iterables))将始终具有与最短迭代相同的长度。

因此list(map(lambda x:[int(c) for c in str(x)], somedata))的长度始终与somedata相同。没有办法解决这个问题。

如果所需结果(例如[1,1,2,1,2,3,1,2,3,4,1,2,3,4,5])的项目多于输入(例如[1,12,123,1234,12345]),则必须使用map以外的其他内容来生成它。

例如,您可以使用itertools.chain.from_iterable来展平2个嵌套级别:

In [31]: import itertools as IT

In [32]: somedata = [1,12,123,1234,12345]

In [33]: list(map(int, IT.chain.from_iterable(map(str, somedata))))
Out[33]: [1, 1, 2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4, 5]

或者,为了展平列表列表,sum(..., [])就足够了:

In [44]: sum(map(lambda x:[int(c) for c in str(x)], somedata), [])
Out[44]: [1, 1, 2, 1, 2, 3, 1, 2, 3, 4, 1, 2, 3, 4, 5]

但请注意,这比使用IT.chain.from_iterable要慢得多(见下文)。

这是一个基准(使用IPython' s %timeit)测试10,000个整数列表中的各种方法,从0到100万:

In [4]: import random
In [8]: import functools
In [49]: somedata = [random.randint(0, 10**6) for i in range(10**4)]

In [50]: %timeit list(map(int, IT.chain.from_iterable(map(str, somedata))))
100 loops, best of 3: 9.35 ms per loop

In [13]: %timeit [int(i) for i in list(''.join(str(somedata)[1:-1].replace(', ','')))]
100 loops, best of 3: 12.2 ms per loop

In [52]: %timeit [int(j) for i in somedata for j in str(i)]
100 loops, best of 3: 12.3 ms per loop

In [51]: %timeit sum(map(lambda x:[int(c) for c in str(x)], somedata), [])
1 loop, best of 3: 869 ms per loop

In [9]: %timeit listified = map(lambda x:[int(c) for c in str(x)], somedata); functools.reduce(lambda x,y: x+y,listified,[])
1 loop, best of 3: 871 ms per loop

答案 1 :(得分:2)

有两个想法,一个有列表综合:

print [int(j) for i in somedata for j in str(i) ]

新的东西(来自评论),字符串已经可迭代,所以它将是:

print [int(i) for i in list(''.join(str(somedata)[1:-1].replace(', ','')))]

第二次对字符串和列表综合进行操作:

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

两者的输出:

0k