2016-02-21 28 views
7

Ho creato questo elenco; ogni elemento è una stringa che contiene le virgole (in alcuni casi) e del colon (sempre):Utilizzo di Python Funzioni di ordine superiore per manipolare le liste

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' 
] 

Vorrei creare un nuovo elenco da quello di cui sopra come segue:

['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'] 

Ma io Mi piacerebbe sapere se/come è possibile farlo in una riga o due di codice efficiente che utilizza principalmente le funzioni di ordine superiore di Python. Sto tentando esso:

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

... produce questo:

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

... ma sto lottando con aggiungendo il pezzo di ogni stringa dopo i due punti indietro su ogni articolo.

+0

Perché siete preoccupati sulla lunghezza del codice? Questo sarebbe molto meno mantenibile a lungo termine. – jpmc26

+0

@ jpmc26 Capisco da dove vieni e accetti. Questo per me è più un esercizio esplorativo per comprendere le capacità degli hof di Python. – dstar

risposta

3

si Supponendo veramente bisogno come una lista di stringhe contro un dizionario , che sembra una struttura dati migliore.

Con semplificare l'utilizzo comprehensions si può fare questo:

>>> [[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']] 

Ora basta add gli elenchi:

>>> 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'] 

O semplicemente appiattire la lista:

>>> [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'] 
+0

'flatten' è incorporato come' itertools.chain.from_iterable' – Caridorc

+0

@AChampion grazie. Diverse persone hanno pubblicato un ottimo codice che funziona bene, ma la tua risposta è stata più in linea con il mio obiettivo. – dstar

8

vorrei creare un dict utilizzando, zip, map e itertools.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) 

uscita:

{'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'} 

oppure utilizzando il costruttore dict:

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) 

Se si vuole veramente una lista di stringhe, possiamo fare qualcosa di simile usando itertools.chain e uniscono le sottostringhe:

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)) 

uscita:

['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'] 
1

questo può funzionare: comprehensions

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 
1

Lista sono preferiti in Python (verificare es this), grazie ad una migliore leggibilità (almeno per alcuni;).

Il codice illustra due tipi di nidificazione della lista, il primo è fondamentalmente concatenando le operazioni, l'altro produce una lista da due cicli annidati.

Se fate i vostri dati in modo più coerente con l'aggiunta di uno spazio dopo l'carrots, water, si può sbarazzarsi di due .strip() chiamate;)

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]