将列表推导式转换为函数式编程



我有一个字典列表

lst = [{'a': (1, 2, 3), 'b': (2, 3)},
{'c': (3, 6), 'd': (4, 8), 'e': (5, 10)},
{'d': (6, 12), 'e': (7, 14)}]

对于每个字典中的每个键,我只想保留值的第一个元素。所以期望的输出是

[{'a': 1, 'b': 2}, {'c': 3, 'd': 4, 'e': 5}, {'d': 6, 'e': 7}]
我可以使用像 这样的列表推导式来获取它
[{key: val[0] for key, val in dct.items()} for dct in lst]

然而,我想知道是否有可能使用map, itemgetter, itertools, functools等来获得相同的输出。到目前为止我有什么:

map(dict.values, lst)

但我不知道该怎么走。

对于嵌套迭代,我认为如果没有lambda表达式的帮助,我们无法做到:

from operator import itemgetter, methodcaller
list(map(
lambda items: dict(zip(
map(itemgetter(0), items),
map(itemgetter(0), map(itemgetter(1), items))
)), map(methodcaller('items'), lst)))
# [{'a': 1, 'b': 2}, {'c': 3, 'd': 4, 'e': 5}, {'d': 6, 'e': 7}]

我不得不说它很丑。

更新:我找到了一种方法来避免lambda:

  1. 首先,根据注释区,我们对上面的表达式进行简化(这里省略最外层的列表,以降低理解难度):
func = lambda d: dict(zip(d, map(itemgetter(0), d.values())))
map(func, lst)
  1. 很容易观察到dict可以移动到lambda之外。我们只需要添加另一个map:
func = lambda d: zip(d, map(itemgetter(0), d.values()))
map(dict, map(func, lst))
  1. 同样,我们可以将zip移到lambda之外:
func = lambda d: map(itemgetter(0), d.values())
map(dict, map(zip, lst, map(func, lst)))
  1. 这似乎是结束了,似乎没有办法将lambda转换为多个内置函数的组合,但仍然有方法,让我们首先尝试将d.values移到lambda之外。在这里,由于列表的元素类型是确定的,我们直接使用dict.values而不是operator.methodcaller:
func = lambda values: map(itemgetter(0), values)
map(dict, map(zip, lst, map(func, map(dict.values, lst))))
  1. 答案马上就出来了。我们可以通过使用functools.partial:
  2. 来消除lambda
map(dict, map(zip, lst, map(partial(map, itemgetter(0)), map(dict.values, lst))))

测试:

>>> from operator import itemgetter
>>> from functools import partial
>>> lst = [{'a': (1, 2, 3), 'b': (2, 3)},
...        {'c': (3, 6), 'd': (4, 8), 'e': (5, 10)},
...        {'d': (6, 12), 'e': (7, 14)}]
>>> map(dict, map(zip, lst, map(partial(map, itemgetter(0)), map(dict.values, lst))))
<map object at 0x000002A0542CBB20>
>>> list(_)
[{'a': 1, 'b': 2}, {'c': 3, 'd': 4, 'e': 5}, {'d': 6, 'e': 7}]

相关内容

  • 没有找到相关文章

最新更新