Wie entferne ich \ n aus einem Listenelement?

77

Ich versuche, Python zu einer Lesezeile aus einer TXT-Datei zu bringen und die Elemente der ersten Zeile in eine Liste zu schreiben. Die Elemente in der Datei waren durch Tabulatoren getrennt, daher habe ich split("\t")die Elemente getrennt. Da die TXT-Datei viele Elemente enthält, habe ich die in jeder Zeile gefundenen Daten in einer separaten Liste gespeichert.

Das Problem, das ich derzeit habe, ist, dass es jede Liste wie folgt anzeigt:

['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3\n']

Wie kann ich \naus dem letzten Element der Liste entfernen und es gerecht machen '7.3'?

Herr Wotan
quelle
Verwenden Sie für die Daten, die Sie haben, einfach split () (keine Argumente). Zuerst wird das Leerzeichen entfernt und dann das Leerzeichen aufgeteilt.
JoshD

Antworten:

144

Wenn Sie \nnur aus dem letzten Element entfernen möchten , verwenden Sie Folgendes:

t[-1] = t[-1].strip()

Wenn Sie \nalle Elemente entfernen möchten , verwenden Sie Folgendes:

t = map(lambda s: s.strip(), t)

Sie können auch entfernen, \n bevor Sie die Linie teilen:

line = line.strip()
# split line...
Bolo
quelle
5
Ich würde einen Streifen machen, bevor ich mich aufspalte ... ich fühle mich prägnanter.
st0le
2
Huzzah! Es klappt! Vielen Dank.
Herr Wotan
8
Wenn ich die Liste durchlaufen würde, würde ich sie auch verwenden [s.strip() for s in t]. Ich habe es zeitlich festgelegt und es ist 5,33 ms zu verarbeiten ["s\n"]*10000gegenüber 9,73 ms für map. mapwird gewinnen, wenn es ein eingebautes abbildet.
Aaronasterling
3
line = line.strip()entfernt ALL TRAILING WHITESPACE. Das ist Metzgerei. Lesen Sie die Antwort von Jim Dennis.
John Machin
1
@ John True. Darüber hinaus werden alle führenden Leerzeichen entfernt. In vielen Fällen line.strip()wäre es vernünftiger als line.rstrip('\n')und deshalb habe ich es ohne weitere Erklärung geschrieben. In diesem Fall (durch Tabulatoren getrennte Werte) haben Sie jedoch 100% Recht: Man sollte in der Tat vorsichtig sein, wenn führende und nachfolgende Leerzeichen entfernt werden, da eine leere erste oder letzte Spalte möglicherweise "verschwindet".
Bolo
48

Ab Python3

mapgibt nicht mehr a zurück, listsondern a mapObject, daher sieht die Antwort ungefähr so ​​aus

>>> map(lambda x:x.strip(),l)
<map object at 0x7f00b1839fd0>

Sie können mehr darüber auf lesen Was ist neu in Python 3.0 .

map()und filter()Rückgabe von Iteratoren. Wenn Sie wirklich eine brauchen list, ist eine schnelle Lösung zlist(map(...))

Wie kann man nun durchkommen?


Fall 1 - Der listAnruf mapmit alambda

mapGibt einen Iterator zurück . listist eine Funktion, die einen Iterator in eine Liste konvertieren kann. Daher müssen Sie einen listAnruf abschließen map. Die Antwort lautet nun:

>>> l = ['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3\n']
>>> list(map(lambda x:x.strip(),l))
['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3']

Sehr gut, wir bekommen die Ausgabe. Jetzt überprüfen wir, wie lange es dauert, bis dieser Code ausgeführt wird.

$ python3 -m timeit "l = ['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3\n'];list(map(lambda x:x.strip(),l))"
100000 loops, best of 3: 2.22 usec per loop

2,22 Mikrosekunden. Das ist nicht so schlimm Aber gibt es effizientere Wege?


Fall 2 - Der listAnruf mapohne alambda

lambdawird von vielen in der Python-Community (einschließlich Guido ) missbilligt . Abgesehen davon wird die Geschwindigkeit des Programms erheblich reduziert. Daher müssen wir dies so weit wie möglich vermeiden. Die Toplevel-Funktion str.strip. Kommt uns hier zu Hilfe.

Das mapkann ohne Verwendung lambdavon str.stripas neu geschrieben werden

>>> list(map(str.strip,l))
['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3']

Und jetzt zu den Zeiten.

$ python3 -m timeit "l = ['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3\n'];list(map(str.strip,l))"
1000000 loops, best of 3: 1.38 usec per loop

Fantastisch. Sie können die Effizienzunterschiede zwischen den beiden Möglichkeiten erkennen. Es ist fast 60% schneller. Daher ist der Ansatz ohne Verwendung von a lambdahier eine bessere Wahl.


Fall 3 - Befolgen Sie die Richtlinien, den regulären Weg

Ein weiterer wichtiger Punkt von Was ist neu in Python 3.0? Es wird empfohlen, dies nach Möglichkeit zu vermeiden map.

Besonders knifflig wird map()für die Nebenwirkungen der Funktion aufgerufen; Die richtige Transformation besteht darin, eine reguläre forSchleife zu verwenden (da das Erstellen einer Liste nur verschwenderisch wäre).

So können wir dieses Problem ohne mapeine reguläre forSchleife lösen .

Die triviale Art der Lösung (die Brute-Force) wäre:

>>> l = ['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3\n']
>>> final_list = []
>>> for i in l:
...     final_list.append(i.strip())
... 
>>> final_list
['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3']

Das Timing-Setup

def f():
    l = ['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3\n']
    final_list = []
    for i in l:
         final_list.append(i.strip())
import timeit
print(min(timeit.repeat("f()","from __main__ import f")))

Und das Ergebnis.

1.5322505849981098

Wie Sie sehen, ist die Brute-Force hier etwas langsamer. Für einen normalen Programmierer ist es jedoch definitiv besser lesbar als eine mapKlausel.


Fall 4 - Listenverständnisse

Ein Listenverständnis ist hier ebenfalls möglich und entspricht dem in Python2.

>>> [i.strip() for i in l]
['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3']

Nun zu den Timings:

$ python3 -m timeit "l = ['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3\n'];[i.strip() for i in l]"
1000000 loops, best of 3: 1.28 usec per loop

Wie Sie sehen, ist das Listenverständnis effektiver als map(auch das ohne a lambda). Daher lautet die Daumenregel in Python3, stattdessen ein Listenverständnis zu verwendenmap


Fall 5 - In-Place-Mechanismen und Raumeffizienz ( TMT )

Eine letzte Möglichkeit besteht darin, die Änderungen in der Liste selbst vorzunehmen. Dies spart viel Speicherplatz. Dies kann mit erfolgen enumerate.

>>> l = ['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3\n']
>>> for i,s in enumerate(l):
...     l[i] = s.strip()
... 
>>> l
['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3']

Das Timing-Ergebnis wäre 1.4806894720022683. Dieser Weg ist jedoch platzsparend.


Fazit

Eine vergleichende Liste von Timings (sowohl Python 3.4.3 als auch Python 3.5.0)

----------------------------------------------------
|Case| method          | Py3.4 |Place| Py3.5 |Place|
|----|-----------------|-------|-----|-------|-----|
| 1  | map with lambda | 2.22u | 5   | 2.85u | 5   |
| 2  | map w/o lambda  | 1.38u | 2   | 2.00u | 2   |
| 3  | brute-force     | 1.53u | 4   | 2.22u | 4   |
| 4  | list comp       | 1.28u | 1   | 1.25u | 1   |
| 5  | in-place        | 1.48u | 3   | 2.14u | 3   |
----------------------------------------------------

Beachten Sie schließlich, dass das Listenverständnis der beste und die mapVerwendung lambdader schlechteste ist. Aber nochmal --- NUR IN PYTHON3

Bhargav Rao
quelle
11

Es hört sich so an, als ob Sie so etwas wie die Perl- chomp()Funktion wollen.

Das ist in Python trivial:

def chomp(s):
    return s[:-1] if s.endswith('\n') else s

... vorausgesetzt, Sie verwenden Python 2.6 oder höher. Ansonsten benutze einfach das etwas ausführlichere:

def chomp(s):
    if s.endwith('\n'):
        return s[:-1]
    else:
        return s

Wenn Sie alle neuen Zeilen vom Ende einer Zeichenfolge entfernen möchten (in dem ungeraden Fall, in dem aus irgendeinem Grund mehrere nachfolgende Zeilenumbrüche vorhanden sein können):

def chomps(s):
    return s.rstrip('\n')

Offensichtlich sollten Sie niemals eine solche Zeichenfolge sehen, die von normalen Python-Dateiobjekten readline()oder readlines()Methoden zurückgegeben wird.

Ich habe gesehen, wie Leute blind die letzten Zeichen (mit s[:-1]Slicing) aus den Ergebnissen von Dateien readline()und ähnlichen Funktionen entfernt haben. Dies ist eine schlechte Idee, da dies zu einem Fehler in der letzten Zeile der Datei führen kann (falls eine Datei mit etwas anderem als einer neuen Zeile endet).

Zuerst könnten Sie in ein falsches Sicherheitsgefühl versetzt werden, wenn Sie die letzten Zeichen blind von den Zeilen entfernen, die Sie gelesen haben. Wenn Sie zum Erstellen Ihrer Testsuite-Dateien einen normalen Texteditor verwenden, wird von den meisten stillschweigend eine neue Zeile am Ende der letzten Zeile hinzugefügt. Um eine gültige Testdatei zu erstellen, verwenden Sie folgenden Code:

f = open('sometest.txt', 'w')
f.write('some text')
f.close()

... und wenn Sie diese Datei erneut öffnen und die Methoden readline()oder readlines()file verwenden, werden Sie feststellen, dass der Text ohne den nachfolgenden Zeilenumbruch gelesen wird.

Dieses Versäumnis, Textdateien zu berücksichtigen, die auf Zeichen ohne Zeilenumbruch enden, hat viele UNIX-Dienstprogramme und Skriptsprachen seit vielen Jahren geplagt. Es ist ein dummer Eckfehler, der sich gerade oft genug in den Code einschleicht, um ein Schädling zu sein, aber nicht oft genug, damit die Leute daraus lernen können. Wir könnten argumentieren, dass "Text" -Dateien ohne den ultimativen Zeilenumbruch "beschädigt" oder nicht standardisiert sind. und das kann für einige Programmierspezifikationen gültig sein.

Es ist jedoch allzu einfach, Eckfälle in unserer Codierung zu ignorieren und diese Unwissenheit Menschen zu beißen, die später von Ihrem Code abhängig sind. Wie meine Frau sagt: Wenn es um Programmierung geht ... üben Sie sicheres Hex!

Jim Dennis
quelle
1
+1 Wenn Sie eine Python-Textdatei lesen, line = line.rstrip('\n')sollten Sie vor dem Parsen der Zeile in Felder überprüfen, ob eine neue Zeile vorhanden ist (oder diese blind entfernen, wenn sie vorhanden ist ).
John Machin
6

Listenverständnis verwenden:

myList = ['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3\n']

[(el.strip()) for el in myList]
rogeriopvl
quelle
Dies setzt voraus, dass beabsichtigt wird, alle führenden und nachfolgenden Leerzeichen zu entfernen. Das ist keine genaue Übereinstimmung, um "nachfolgende neue Zeilen zu entfernen".
Jim Dennis
3

von diesem Link :

Sie können die Methode rstrip () verwenden. Beispiel

mystring = "hello\n"    
print(mystring.rstrip('\n'))
itagomo
quelle
2

Als alternative Methode können Sie split () verwenden (ohne Argumente), wenn Sie wissen, dass Ihre Daten keine Leerzeichen enthalten, was anscheinend der Fall ist. Dies teilt sich auf Leerzeichen auf und verwendet einen effizienteren Algorithmus als die andere Version von Split. Außerdem werden an beiden Enden Leerzeichen entfernt.

line = line.split()

Und das ist es.

JoshD
quelle
2

Du könntest es tun -

DELIMITER = '\t'
lines = list()
for line in open('file.txt'):
    lines.append(line.strip().split(DELIMITER))

Das lineshat den gesamten Inhalt Ihrer Datei.

Man könnte auch Listenverständnisse verwenden, um dies kompakter zu machen.

lines = [ line.strip().split(DELIMITER) for line in open('file.txt')]
Srikar Appalaraju
quelle
Ich verwende eine Variante dieses Ansatzes, um eine Datei in eine einzeilige Javascript-Variable umzuwandeln. nett. danke Srikar
zach
2

Dies wird auch funktionieren,

f=open('in.txt','r')

    for line in f:
            parline = line[:-1].split(',')
betrunken
quelle
2

str.strip () entfernt die Leerzeichen. Sie können auch benutzerdefinierte Zeichen als Argument an Strip übergeben. Die Strip- Funktion entfernt die Leerzeichen / benutzerdefinierten Zeichen an beiden Enden der Zeichenfolge. lstrip () und rstrip () sind Funktionen für den linken bzw. rechten Streifen.

Z.B:

test_str = "Vishaka\n" 
test_str = test_str.strip()

test_str ist jetzt Vishaka

Gopalkoduri
quelle
1

Sie greifen auf das letzte Element der Menge zu und speichern den Wert in einer Variablen.

Also hast du:

fileName = '7.3\n'

dann mach einfach:

fileName.strip()

was dich mit verlassen wird 7.3. Speichern Sie diesen Wert dann wieder im letzten Element der Menge.

Sie können nur die linke oder rechte Seite verwenden lstrip()oder rstrip()entfernen.

Pavan
quelle
1

Da es bei der Frage des OP darum geht, das Zeilenumbruchzeichen vom letzten Element zu entfernen, würde ich es zurücksetzen mit the_list[-1].rstrip():

>>> the_list = ['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3\n']
>>> the_list[-1] = ls[-1].rstrip()
>>> the_list
['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3']

Es ist O (1).

Srisaila
quelle
0

Dies funktioniert, um die \n(neue Zeile) von einem Element in einer Liste zu entfernen, wobei nur das erste Element in der Zeichenfolge entfernt wird

def remove_end(s):
    templist=[]
    for i in s:
        templist.append(i)
    return(templist[0])
sryzr
quelle
0

Ich hatte dieses Problem und löste es mit der oben beschriebenen Chomp-Funktion:

def chomp(s):
    return s[:-1] if s.endswith('\n') else s

def trim_newlines(slist):
    for i in range(len(slist)):
        slist[i] = chomp(slist[i])
    return slist
.....
names = theFile.readlines()
names = trim_newlines(names)
....
catchpolej
quelle
1
Dies scheint nur ein Duplikat früherer Antworten zu sein. Wenn es etwas hinzufügt, machen Sie klar, was das ist.
Blm
0

\r\nVerwenden Sie Splitlines , um mit vielen Zeilenumbruchbegrenzern umzugehen, einschließlich Zeichenkombinationen wie . Kombinieren Sie kommen und Teilungslinien entfernen / ersetzen Sie alle Zeilenumbrüche aus einem String s:

''.join(s.splitlines())

So entfernen Sie genau einen nachlauf Newline, übergibt Trueals keependsArgument , um die Trennzeichen beibehalten, das Entfernen nur die Trennzeichen in der letzten Zeile:

def chomp(s):
    if len(s):
        lines = s.splitlines(True)
        last = lines.pop()
        return ''.join(lines + last.splitlines())
    else:
        return ''
teichert
quelle
0
new_list = ['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3\n']
for i in range(len(new_list)):
    new_list[i]=new_list[i].replace('\n','')
print(new_list)

Die Ausgabe wird so sein

['Name1', '7.3', '6.9', '6.6', '6.6', '6.1', '6.4', '7.3']
Tanmoy Datta
quelle