2017-05-02 3 views
6

Das Problem ist wie folgt. Ich habe eine Liste von StringsVerknüpfen ausgewählter Strings in der Liste der Strings

lst1=['puffing','his','first','cigarette','in', 'weeks', 'in', 'weeks'] 

und ich möchte die Zeichenfolge erhalten

lst2=['puffing','his','first','cigarette','in weeks', 'in weeks'] 

, die alle Vorkommen des sublist ['in', 'weeks'] Gründen verketten, die hier nicht relevant sind, wo find_sub_list1 genommen wird von here (und unten in dem Code enthalten):

npis = [['in', 'weeks'], ['in', 'ages']] 

# given a list a candidate sublist, return the index of the first and last 
# element of the sublist within the list 
def find_sub_list1(sl,l): 
    results=[] 
    sll=len(sl) 
    for ind in (i for i,e in enumerate(l) if e==sl[0]): 
     if l[ind:ind+sll]==sl: 
     results.append((ind,ind+sll-1)) 

    return results 

def concatenator(sent, npis): 
    indices = [] 
    for npi in npis: 
     indices_temp = find_sub_list1(npi, sent) 
     if indices_temp != []: 
      indices.extend(indices_temp) 
    sorted(indices, key=lambda x: x[0]) 

    for (a,b) in indices: 
     diff = b - a 
     sent[a:b+1] = [" ".join(sent[a:b+1])] 
     del indices[0] 
     indices = [(a - diff, b - diff) for (a,b) in indices] 

    return sent 

anstelle des gewünschten lst2 Dieser Codierer retur ns:

concatenator(lst1,['in', 'weeks']) 
>>['puffing','his','first','cigarette','in weeks', 'in', 'weeks'] 

so verkettet es nur das erste Auftreten. Irgendwelche Ideen, wo der Code versagt?

+2

einen besseren Weg, die beiden Wörter zu verketten wäre nach hinten zu arbeiten. so müssen Sie die restlichen Indizes nicht mit dem 'diff' anpassen. – aydow

+0

Wie habe ich das vermisst! Großer Vorschlag! Danke vielmals! –

Antwort

0

dies keine Lösung für Ihren Code ist, aber eine alternative Lösung (ich immer für alles, was mit regex am Ende)

import re 
list1_str = ','.join(lst1) 
npis_concat = [','.join(x) for x in npis] 
for item in npis_concat: 
    list1_str = re.sub(r'\b'+item+r'\b',item.replace(',', ' '),list1_str) 
lst1 = list1_str.split(',') 

ich ein Komma hier, aber Sie können es mit einem beliebigen Zeichen zu ersetzen, vorzugsweise ein Sie nicht in Ihrem Text sein wissen

die r'\b' werden verwendet, um sicherzustellen, dass wir nicht aus Versehen von Bits aus Worten hacken Sie endet/beginnt mit Sachen in NPIs

2

, da die gewünschte Untersequenz ist 'in' 'weeks'und möglicherweise 'in''ages'

Eine mögliche Lösung könnte sein (der Looping wenn auch nicht sehr elegant ist):

  1. zunächst alle Positionen finden, wo 'in' auftritt.

  2. dann durch die Quellenliste iterieren, Elemente der Zielliste angehängt wird, und die Positionen der 'in' speziell zu behandeln, das heißt, wenn das folgende Wort in einem speziellen Satz ist dann die beiden verbinden & an das Ziel anzuhängen, der Iterator vorrückenden eine zusätzliche Zeit.

  3. Sobald die Quellenliste erschöpft ist, wird ein IndexError ausgelöst, der anzeigt, dass wir die Schleife unterbrechen sollten.

Code:

index_in = [i for i, _ in enumerate(lst1) if _ == 'in'] 

lst2 = []; n = 0 

while True: 
    try: 
     if n in index_in and lst1[n+1] in ['weeks', 'ages']: 
      lst2.append(lst1[n] + lst1[n+1]) 
      n += 1 
     else: 
      lst2.append(lst1[n]) 
     n += 1 
    except IndexError: 
     break 

Eine bessere Möglichkeit, dies zu tun wäre durch reguläre Ausdrücke sein.

  1. verbinden die Liste in eine Zeichenkette mit Leerzeichen als Trennzeichen

  2. spaltete die Liste auf Räume, ausgenommen die von in<space>weeks umgeben Flächen.Hier können wir negative Vorschau & Lookbehind

Code verwenden:

import re 

c = re.compile(r'(?<!in) (?!weeks)') 

lst2 = c.split(' '.join(lst1)) 
Verwandte Themen