使用 Python 高阶函数来操作列表

Using Python Higher Order Functions to Manipulate Lists

我列出了这份清单;每一项都是一个包含逗号(在某些情况下)和冒号(总是)的字符串:

dinner = [
    'cake,peas,cheese : No',
    'duck,broccoli,onions : Maybe',
    'motor oil : Definitely Not',
    'pizza : Damn Right',
    'ice cream : Maybe',
    'bologna : No',
    'potatoes,bacon,carrots,water: Yes',
    'rats,hats : Definitely Not',
    'seltzer : Yes',
    'sleeping,whining,spitting : No Way',
    'marmalade : No'
]

我想根据上面的列表创建一个新列表,如下所示:

['cake : No',
 'peas : No',
 'cheese : No',
 'duck : Maybe',
 'broccoli : Maybe',
 'onions : Maybe',
 'motor oil : Definitely Not',
 'pizza : Damn Right',
 'ice cream : Maybe',
 'bologna : No',
 'potatoes : Yes',
 'bacon : Yes',
 'carrots : Yes',
 'water : Yes',
 'rats : Definitely Not',
 'hats : Definitely Not',
 'seltzer : Yes',
 'sleeping : No Way',
 'whining : No Way',
 'spitting : No Way',
 'marmalade : No']

但我想知道是否/如何在主要使用 Python 的高阶函数的一两行高效代码中做到这一点。我一直在尝试:

reduce(lambda x,y: x + y, (map(lambda x: x.split(':')[0].strip().split(','), dinner)))

...产生这个:

['cake',
 'peas',
 'cheese',
 'duck',
 'broccoli',
 'onions',
 'motor oil',
 'pizza',
 'ice cream',
 'bologna',
 'potatoes',
 'bacon',
 'carrots',
 'water',
 'rats',
 'hats',
 'seltzer',
 'sleeping',
 'whining',
 'spitting',
 'marmalade']

...但我正在努力将冒号后的每个字符串的一部分附加到每个项目上。

我会使用 zipmapitertools.repeat:

创建一个字典
from itertools import repeat


data = ({k.strip(): v.strip() for _k, _v in map(lambda x: x.split(":"), dinner)
     for k, v in zip(_k.split(","), repeat(_v))})

from pprint import pprint as pp

pp(data)

输出:

{'bacon': 'Yes',
 'bologna': 'No',
 'broccoli': 'Maybe',
 'cake': 'No',
 'carrots': 'Yes',
 'cheese': 'No',
 'duck': 'Maybe',
 'hats': 'Definitely Not',
 'ice cream': 'Maybe',
 'marmalade': 'No',
 'motor oil': 'Definitely Not',
 'onions': 'Maybe',
 'peas': 'No',
 'pizza': 'Damn Right',
 'potatoes': 'Yes',
 'rats': 'Definitely Not',
 'seltzer': 'Yes',
 'sleeping': 'No Way',
 'spitting': 'No Way',
 'water': 'Yes',
 'whining': 'No Way'}

或者使用字典构造函数:

from itertools import repeat

data = dict(map(str.strip, t) for _k, _v in map(lambda x: x.split(":"), dinner)
            for t in zip(_k.split(","), repeat(_v)))

from pprint import pprint as pp

pp(data)

如果你真的想要一个字符串列表,我们可以使用 itertools.chain 并连接子字符串来做类似的事情:

from itertools import repeat, chain

data = chain.from_iterable(map(":".join, zip(_k.split(","), repeat(_v))) 
                           for _k, _v in map(lambda x: x.split(":"), dinner))


from pprint import pprint as pp

pp(list(data))

输出:

['cake: No',
 'peas: No',
 'cheese : No',
 'duck: Maybe',
 'broccoli: Maybe',
 'onions : Maybe',
 'motor oil : Definitely Not',
 'pizza : Damn Right',
 'ice cream : Maybe',
 'bologna : No',
 'potatoes: Yes',
 'bacon: Yes',
 'carrots: Yes',
 'water: Yes',
 'rats: Definitely Not',
 'hats : Definitely Not',
 'seltzer : Yes',
 'sleeping: No Way',
 'whining: No Way',
 'spitting : No Way',
 'marmalade : No']

这可能有效:

def processList (aList):
    finalList = []
    for aListEntry in aList:
        aListEntry_entries = aListEntry.split(':')
        aListEntry_list = aListEntry_entries[0].split(',')
        for aListEntry_list_entry in aListEntry_list:
            finalList.append(aListEntry_list_entry.strip() + ' : ' + aListEntry_entries[1].strip())
    return finalList

列表推导在 Python 中是首选(检查例如 this),因为更好的易读性(至少对某些人而言;)。

该代码演示了两种类型的列表理解嵌套,第一种基本上是链接操作,另一种从两个嵌套循环生成一个列表。

如果您通过在 carrots, water 之后添加一个 space 使您的数据更加一致,您可以摆脱两个 .strip() 调用;)

dinner = [
    'cake,peas,cheese : No',
    'duck,broccoli,onions : Maybe',
    'motor oil : Definitely Not',
    'pizza : Damn Right',
    'ice cream : Maybe',
    'bologna : No',
    'potatoes,bacon,carrots,water : Yes',
    'rats,hats : Definitely Not',
    'seltzer : Yes',
    'sleeping,whining,spitting : No Way',
    'marmalade : No'
]

prefs = [(pref, items.split(',')) for items, pref in [it.split(" : ") for it in dinner]]
[" : ".join([item, pref]) for pref, items in prefs for item in items]

假设您确实需要它作为字符串列表而不是字典,这看起来是更好的数据结构。

通过使用推导式进行简化,您可以这样做:

>>> [[x+':'+y for x in i.split(',')]
...  for i, y in map(lambda l: map(str.strip, l.split(':')), dinner)]
[['cake:No', 'peas:No', 'cheese:No'],
 ['duck:Maybe', 'broccoli:Maybe', 'onions:Maybe'],
 ['motor oil:Definitely Not'],
 ...
 ['marmalade:No']]

现在 add 列表:

>>> from operator import add
>>> reduce(add, ([x+':'+y for x in i.split(',')]
...              for i, y in map(lambda l: map(str.strip, l.split(':')), dinner)), [])
['cake:No',
 'peas:No',
 'cheese:No',
 'duck:Maybe',
 ...
 'marmalade:No']

或者只是展平列表:

>>> [a for i, y in map(lambda l: map(str.strip, l.split(':')), dinner) 
...  for a in (x+':'+y for x in i.split(','))]
['cake:No',
 'peas:No',
 'cheese:No',
 'duck:Maybe',
 ...
 'marmalade:No']