2014-04-06 6 views
5

Przepraszamy za niewyraźny tytuł, ale trudno to wyjaśnić zwięźle.Najlepszy sposób na podzielenie każdego n-tego elementu ciągu i scalenie w tablicy?

Zasadniczo wyobrazić Mam listę (w Pythonie), który wygląda tak:

['a', 'b', 'c\nd', 'e', 'f\ng', 'h', 'i'] 

od tego, chcę uzyskać to:

['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'] 

jeden sposób myślałem o robi ten używał reduce tak:

reduce(lambda x, y: x + y.split('\n'), lst, []) 

Ale nie sądzę, że to jest bardzo wydajne, ponieważ nie korzysta z tego, że wiemy, że każdy n-ty element ma w sobie separator. Jakieś sugestie?

Edytuj: więcej informacji na temat budowy tablicy, co może być problemem.

Mam tekstu w postaci:

Ignorable line 
Field name 1|Field name 2|Field name 3|Field name 4 
Value 1|Value 2|Value 3|Value 4 
Value 1|Value 2|Value 3|Value 4 
... 

Gdzie możemy mieć dowolną ilość nazw pól, a nie będzie zawsze taka sama liczba wartości jako nazwy pól w linii. Zauważ, że możemy mieć nowe linie w wartościach. Wiemy tylko, że będą oddzielone znakiem "|". Więc mogliśmy mieć

Value 1|This is an long 
value that extends over multiple 
lines|Value 3|Value 4 

Jak obecnie zrobić to wykonując s.split('\n', 2) tak, że otrzymujemy nazwy pól we własnym ciąg i wartości we własnym ciąg. Następnie, dzieląc wartości przez "|", otrzymujemy listę pierwotnie wspomnianej formy.

+1

co masz na myśli każdy element n-ty ... to wygląda twoje n zmienia się z 3 na 2 ... poza tym prawdopodobnie dużo szybko ... chyba że tak naprawdę nie, ale w takim przypadku wiedziałbyś, że to było twoje wąskie gardło ....przedwczesna optymalizacja jest źródłem wszelkiego zła –

+1

W przykładzie \ n zawsze następuje po trzecim elemencie (c jest trzecią literą alfabetu, f jest szóstą). Jestem ciekawy, co powoduje, że dostajesz pierwszą listę w tym formacie. Być może kod byłby czystszy, gdybyś zmienił sposób konstruowania oryginalnej listy ... to wygląda na obejście uszkodzonego parsera. – ramcdougal

+0

@ramcdougal może się zdarzyć, że nie jest to najlepszy sposób na skonstruowanie tej listy. Zaktualizuję wiadomość o tym, jak ją otrzymałem w tej formie. – mp94

Odpowiedz

10

Możesz po prostu zrobić ('\n'.join(lst)).split(), aby uzyskać drugą listę.

In [17]: 

%timeit reduce(lambda x, y: x + y.split('\n'), lst, []) 
100000 loops, best of 3: 9.64 µs per loop 
In [18]: 

%timeit ('\n'.join(lst)).split() 
1000000 loops, best of 3: 1.09 µs per loop 

Dzięki @Joran Beasley za sugerowanie split() nad split('\n')!

Edit

Teraz widzę zaktualizowaną pytanie, myślę, że możemy uniknąć w takiej sytuacji na początku, zobaczyć (za pomocą re):

In [71]: 

L=re.findall('([^|]+)\|', 
      ''.join(['|'+item+'|' if item.count('|')==3 else item for item in S.split('\n')[1:]])+'|') 
In [72]: 

zip(*[L[i::4] for i in range(4)]) #4 being the number of fields. 
Out[72]: 
[('Field name 1', 'Field name 2', 'Field name 3', 'Field name 4'), 
('Value 1', 'Value 2', 'Value 3', 'Value 4'), 
('Value 1', 
    'This is an longvalue that extends over multiplelines', 
    'Value 3', 
    'Value 4')] 

Wygląda na zbiorze dla SAS początkowo , czy mam rację?

+0

To zdecydowanie dużo szybciej, ale mogą też istnieć nowe linie w innych elementach (może to być wiele, nieznane ilości). Zaktualizuję post z tymi informacjami. – mp94

+0

Masz szansę rozwiązać problem? Jeśli nie, zobacz edycję. –

+0

Zrobiłem, ale to też by zadziałało. Dane wyjściowe, które analizuję, są w rzeczywistości żądaniami zapytania WQL, przy użyciu narzędzia wmic w systemie Linux. Zobacz http://www.aldeid.com/wiki/Wmic-linux – mp94

2

przedwczesna optymalizacja jest źródłem wszelkiego zła

jeśli rzeczywiście występują problemy z wydajnością spowodowane tym kodem thats jedno, ale wątpię jesteś.

podczas optymalizacji jesteś często poświęcając czytelność, co bym zrobił gdyby było mi

list(itertools.chain(*[item.split() for item in lst])) 

co jest bardzo jasne, co robisz

+1

Cześć Joran, jesteś pewien, że to zadziała? Myślę, że powinno to być 'list (itertools.chain (* [item.split() dla pozycji w lst]))' –

+0

ahh twoja całkowicie słuszna twoja odpowiedź jest lepsza pod względem klarowności myślę, że i tak ("chociaż id prawdopodobnie po prostu użyć normalny podział bez separatora, ale meh) –

Powiązane problemy