Se non si è autorizzati a importare nulla poi un ingegnoso reduce
operazione insieme a slicing
e zip
(tutti questi sono Python built-in, che non richiede l'importazione) potrebbe essere un modo molto compatto per farlo:
EDIT Dopo avermi fatto notare che avevo frainteso il problema, l'ho risolto modificando l'istruzione zip()
.
# the string - split it immediately into a list of words
# (some words deleted to make it smaller)
words = "dimension implies direction implies the more and the less".split()
# There is a **lot** going on in this line of code, explanation below.
result = reduce(lambda acc, kv: acc.setdefault(kv[0], []).append(kv[1]) or acc,
zip(words[1:], words[:-1]), {})
# this was the previous - incorrect - zip()
# zip(words[1::2], words[0::2]), {})
E in uscita il risultato (anche a cura)
print result
{'and': ['more'], 'direction': ['implies'], 'implies': ['dimension',
'direction', 'measurement'], 'less': ['the'], 'measurement':['implies'],
'the': ['implies', 'and'], 'more': ['the']}
Per completezza, il vecchio, erronei, risultato:
print result
{'the': ['and'], 'implies': ['dimension', 'direction', 'measurement'], 'more': ['the']}
Un po 'di spiegazione
Dopo aver diviso la stringa in un elenco di parole, possiamo indicizzare le singole parole come words[i]
.
modificato In base all'affermazione del problema, i tasti del dict risultante sono le parole che seguono una parola, il valore è la prima parola. Quindi dobbiamo trasformare la lista di parole in una lista di combinazioni di ogni parola con la parola successiva. Quindi la lista di key
sarà la lista [parole [1], parole [2], parole [3], ....] e lo values
che vanno con quelli sono: [parole [0], parole [1 ], parole [2], ..., parole [n-1]].
Usare Python slicing
: keys = words[1:]
e values = words[:-1]
Ora abbiamo bisogno di creare un dict
di quelle chiavi e valori, aggregando i valori in un list
, se la stessa chiave si verifica più volte.
Un dict
ha un metodo .setdefault(key, value)
che inizializza valore s' key
a value
se key
non è in ancora il dict
, altrimenti restituisce il valore come è attualmente. Per impostazione predefinita, inizializzando tutti i valori sul numero vuoto list
([]
), possiamo chiamare ciecamente .append(...)
su di esso. Questo è ciò che questa parte del codice fa:
acc.setdefault(key, []).append(value)
Poi c'è reduce
. Un'operazione di riduzione riduce (...) un elenco di valori in uno. In questo caso ridurremo un elenco di tuple (key, value)
in un dict
in cui abbiamo accumulato tutti i valori nella rispettiva chiave.
reduce
accetta una funzione di riduzione della richiamata e un elemento iniziale. L'elemento iniziale qui è il dict vuoto {}
- lo riempiremo mentre procediamo.
La funzione di riduzione della richiamata viene richiamata ripetutamente con due argomenti, l'accumulatore e l'elemento successivo da aggiungere all'accumulo. La funzione dovrebbe restituire il nuovo accumulatore.
In questo codice, il passaggio di riduzione è sostanzialmente l'aggiunta del valore dell'elemento all'elenco di valori per la chiave dell'elemento. (Vedi sopra - questo è ciò che fa lo .setdefault().append()
).
Tutto ciò che serve è ottenere un elenco di tuple (key, value)
che è necessario elaborare. È qui che viene visualizzato il numero zip
incorporato. zip
accetta due elenchi e restituisce un elenco di tuple di elementi corrispondenti.
Così:
zip(words[1:], words[:-1])
produce esattamente quello che vogliamo: la lista di tutti (key, value)
tuple.
Infine, poiché la funzione di riduzione deve restituire il nuovo accumulatore, dobbiamo giocare un trucco. list.append(...)
restituisce None
, anche se il ditt effettivo è stato modificato. Quindi non possiamo restituire quel valore come accumulatore successivo. Quindi aggiungiamo la costruzione or acc
dopo.
Poiché il lato sinistro della logica or
restituisce sempre None
, che è logicamente False
in Python, il lato destro è sempre 'valutata' - in questo caso la (modificato) dict stesso. Il risultato netto dello or
valuta quindi il dict modificato stesso, che è esattamente quello che dobbiamo restituire.
Mi chiedevo se l'aggiunta di: 'se i == 0: stenence_dict [words_list [i]] = ''' aiuterebbe ad ottenere il valore vuoto per primo indice – Nume
Perché si assegnando 'sentence_dict [words_list [i ]] = words_list [i-1] 'non aggiungendo il valore esistente. Si dovrebbe verificare per 'i == 0' per la prima parola. – ismailsunni
come nota a margine: il primo loop coulp deve essere sostituito con un loop diretto sulle parole –