programmierung.in python
Hallo ich habe ein frage: ich habe ein Datei oder liste dt=["DK"
"D14"
"D34"
"D14"
"D34"
"D50"
"D81"
"D81"
"D91"
"D91"]
wie kann ich machen mit der Python programm sodass für jede element ich nur eine erhalte , ich meine dt =["Dk","D34","D14","D50","D81","D91"]
Danke im voraus
"D14"
"D34"
"D14"
"D34"
"D50"
"D81"
"D81"
"D91"
"D91"]
wie kann ich machen mit der Python programm sodass für jede element ich nur eine erhalte , ich meine dt =["Dk","D34","D14","D50","D81","D91"]
Danke im voraus
@guy12: Was hast Du denn nun, eine Datei oder eine Liste? Falls das da der Inhalt einer Datei ist, sieht der *tatsächlich* genau so aus? Und falls ja, wie ist die Datei zustande gekommen?
@guy12
Wenn es sich um eine Liste handelt, dann erstellst Du mit dessen Elementen eine neue Liste und fügst jedes Element nur dann hinzu, wenn es noch nicht enthalten ist:Falls die Reihenfolge keine Rolle spielt:
mutetella
Wenn es sich um eine Liste handelt, dann erstellst Du mit dessen Elementen eine neue Liste und fügst jedes Element nur dann hinzu, wenn es noch nicht enthalten ist:
Code: Alles auswählen
>>> dt = ['DK', 'D14', 'D34', 'D14', 'D34', 'D50', 'D81', 'D81', 'D91', 'D91']
>>> def equalize(iterable):
... new = []
... for element in iterable:
... if not element in new:
... new.append(element)
... return new
...
>>> equalize(dt)
['DK', 'D14', 'D34', 'D50', 'D81', 'D91']
Code: Alles auswählen
>>> dt = ['DK', 'D14', 'D34', 'D14', 'D34', 'D50', 'D81', 'D81', 'D91', 'D91']
>>> list(set(dt))
['D14', 'DK', 'D34', 'D91', 'D81', 'D50']
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit )
Wenn's auf die Reihenfolge ankommt ist die übliche vorgehensweise:
Code: Alles auswählen
def main():
data = ['DK', 'D14', 'D34', 'D14', 'D34', 'D50', 'D81', 'D81', 'D91', 'D91']
seen = set()
result = list()
for item in data:
if item not in seen:
result.append(item)
seen.add(item)
print result
@BlackJack: Wobei man prinzipiell noch ein paar ``add``-Operationen auf dem Set einsparen kann, wenn man sie nicht wie in deinem Beispiel für wirklich jedes Element ausführt, sondern nur dann, wenn der vorherige Test, den du ja ohnehin machst, ergeben hat, dass das Element bisher noch nicht in ``seen`` steckt. Mag sich in den meisten Fällen nicht allzu stark auf die Gesamtlaufzeit ausführen, tut aber auch nicht weh, wenn man's entsprechend ändert.
Code: Alles auswählen
import sys
import timeit
test = [
'DK', 'D14', 'D34', 'D14', 'D34', 'D50', 'D81', 'D81', 'D91', 'D91'
]
test_1 = '''\
new = []
for element in test:
if not element in new:
new.append(element)
'''
test_2 = '''\
seen = set()
result = list()
for item in test:
if item not in seen:
result.append(item)
seen.add(item)
'''
if __name__ == '__main__':
length = int(sys.argv[1])
test = test * length
print 'test without set: {}'.format(
timeit.timeit(stmt=test_1,
setup='from __main__ import test',
number=10000))
print 'test with set: {}'.format(
timeit.timeit(stmt=test_2,
setup='from __main__ import test',
number=10000))
Code: Alles auswählen
$ python ./equal_items.py 10
test without set: 0.0989220142365
test with set: 0.145992994308
$ python ./equal_items.py 100
test without set: 0.925514936447
test with set: 1.30377697945
$ python ./equal_items.py 1000
test without set: 9.0896999836
test with set: 12.557033062
$ python ./equal_items.py 10000
test without set: 91.0298860073
test with set: 125.113059044
mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit )
@mutetella: Da Du 1. die Verbesserung nicht vorgenommen hast und 2. das nicht in einer Funktion steckt, überrascht es mich jetzt nicht wirklich.
Edit: Und es kommt natürlich auch auf die Anzahl der tatsächlich unterschiedlichen Elemente an.
Edit: Und es kommt natürlich auch auf die Anzahl der tatsächlich unterschiedlichen Elemente an.
@mutetella: überhaupt nicht überraschend. Deine Ergebnisliste ist in jedem Fall 5 Elemente lang. 5 Elemente linear zu durchsuchen braucht eben ein bißchen weniger Zeit als zweimal einen Hash zu ermitteln und zwei Vergleiche. Dass die Zeit linear mit den Wiederholungen Deiner Liste zunimmt ist dann auch wenig überraschend.
@BlackJack
Die Verbesserung reißt's nicht wirklich raus...
... und was Du mit "in einer Funktion steckt" meinst, verstehe ich nicht.
@Sirius3
Ich dachte nur, dass BlackJack's Version performanter sei, da er von "üblicher Vorgehensweise" sprach. Deshalb war ich überrascht.
mutetella
Die Verbesserung reißt's nicht wirklich raus...
Code: Alles auswählen
test_2 = '''\
seen = set()
result = list()
for item in test:
if item not in seen:
result.append(item)
else:
seen.add(item)
'''
Code: Alles auswählen
$ python ./equal_items.py 100
test without set: 0.910356044769
test with set: 1.21818304062
$ python ./equal_items.py 10000
test without set: 90.9470040798
test with set: 121.787957191
@Sirius3
Ich dachte nur, dass BlackJack's Version performanter sei, da er von "üblicher Vorgehensweise" sprach. Deshalb war ich überrascht.
mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit )
@mutetella: Es steckt nicht einer Funktion heisst der Code ist nicht in einer Funktion, sondern, naja, ausserhalb einer Funktion. In meinem Code werden mehr Namen aufgelöst und das ist ausserhalb von Funktionen ”teurer” als bei lokalen Namen in Funktionen.
Meine Version ist üblicherweise auch performanter. Klar kann man Fälle finden bei denen sie das nicht ist, aber generell kann man sagen das mit der Liste ist keine gute Idee weil ``a in b`` bei Listen linear von der Länge der Liste abhängt, während es bei Mengenobjekten völlig egal ist wie viele Objekte da schon drin stehen.
Meine Version ist üblicherweise auch performanter. Klar kann man Fälle finden bei denen sie das nicht ist, aber generell kann man sagen das mit der Liste ist keine gute Idee weil ``a in b`` bei Listen linear von der Länge der Liste abhängt, während es bei Mengenobjekten völlig egal ist wie viele Objekte da schon drin stehen.
@mutetella: Sets haben einen etwas größeren Overhead, aber der Zugriff ist unabhängig von der Länge:
während der Aufwand bei Listen mit der Länge steigt:
Hinzu kommt, dass die Variante mit Set ein Operation pro gefundenem Element mehr hat, so dass der Vorteil von Sets nicht schon bei 1 elementigen Listen überwiegt.
Code: Alles auswählen
>>> for x in range(10): data=set(range(x));print len(data), timeit.timeit(stmt=lambda: 50 in data, number=1000000)
...
0 0.165304899216
1 0.161346912384
2 0.165688991547
3 0.184131145477
4 0.184000968933
5 0.172278881073
6 0.176582098007
7 0.172767877579
8 0.168383836746
9 0.177536964417
Code: Alles auswählen
>>> for x in range(10): data=list(range(x));print len(data), timeit.timeit(stmt=lambda: 50 in data, number=1000000)
...
0 0.164139032364
1 0.178289890289
2 0.211421012878
3 0.227061033249
4 0.257332086563
5 0.271213054657
6 0.296862840652
7 0.32412314415
8 0.342656135559
9 0.360295057297
Die Verbesserung war eher so gemeint, dass ein Element in ``seen`` gesteckt werden soll, wenn es noch *nicht* drin ist. Dein Code macht genau das Gegenteil. Er führt damit von der Funktionweise her zu einem völlig anderem Ergebnis. Zudem sind deine Testfälle ziemlich ungünstig gewählt, wie ja auch schon kommentiert wurde.mutetella hat geschrieben:Die Verbesserung reißt's nicht wirklich raus...Code: Alles auswählen
test_2 = '''\ seen = set() result = list() for item in test: if item not in seen: result.append(item) else: seen.add(item) '''
Was man übrigens noch machen kann:
Die Idee dahinter ist, dass Schleifendurchläufe in reinem Python eingespart werden, weil mittels ``ifilterfalse()`` die bereits gesehenen Elemente aus Python-Sicht übersprungen werden. Ob das tatsächlich soviel bringt, müsste man aber noch testen.
Wenn die ``add``-Operation auf Python-Sets einen Wahrheitswert zurückliefern würde, ob das Element tatsächlich hinzugefügt wurde (nämlich dann, wenn es noch nicht im Set vorhanden war), dann könnte man etwas deutlich Eleganteres mittels ``filter()`` hinbekommen. Der Code würde dann schrumpfen auf:
Code: Alles auswählen
from itertools import ifilterfalse
def get_unique(elems):
result = []
seen = set()
have_seen = seen.__contains__
for elem in ifilterfalse(have_seen, elems):
seen.add(elem)
result.append(elem)
return result
Wenn die ``add``-Operation auf Python-Sets einen Wahrheitswert zurückliefern würde, ob das Element tatsächlich hinzugefügt wurde (nämlich dann, wenn es noch nicht im Set vorhanden war), dann könnte man etwas deutlich Eleganteres mittels ``filter()`` hinbekommen. Der Code würde dann schrumpfen auf:
Code: Alles auswählen
def get_uniques(elems):
seen = set()
return filter(seen.add, elems)
Wer braucht schon einen Kalender...
Sind das nun aussagekräftige Tests oder hab' ich euch tatsächlich noch nicht verstanden?
mutetella
Sag' ruhig, wie es ist: Mein Code ist hirnloser Bullshit!! Ich hab's verbessert...snafu hat geschrieben:Dein Code macht genau das Gegenteil. Er führt damit von der Funktionweise her zu einem völlig anderem Ergebnis.
Ich verstehe nur noch nicht ganz, weshalb. Um zu vergleichen muss ich doch auch jedem Test dieselbe Liste geben. Oder meinst Du mit "Testfälle ziemlich ungünstig gewählt" nur das, was BlackJack mit innerhalb vs. außerhalb einer Funktion schreibt?snafu hat geschrieben:Zudem sind deine Testfälle ziemlich ungünstig gewählt, wie ja auch schon kommentiert wurde.
Code: Alles auswählen
from itertools import ifilterfalse
import sys
import timeit
test = [
'DK', 'D14', 'D34', 'D14', 'D34', 'D50', 'D81', 'D81', 'D91', 'D91'
]
test_01 = '''\
new = []
for element in test:
if not element in new:
new.append(element)
'''
test_02 = '''\
seen = set()
result = list()
for item in test:
if item not in seen:
result.append(item)
seen.add(item)
'''
test_03 = '''\
result = []
seen = set()
have_seen = seen.__contains__
for elem in ifilterfalse(have_seen, test):
seen.add(elem)
result.append(elem)
'''
def unique_01():
new = []
for element in test:
if not element in new:
new.append(element)
def unique_02():
seen = set()
result = list()
for item in test:
if item not in seen:
result.append(item)
seen.add(item)
def unique_03():
result = []
seen = set()
have_seen = seen.__contains__
for elem in ifilterfalse(have_seen, test):
seen.add(elem)
result.append(elem)
if __name__ == '__main__':
length = int(sys.argv[1])
test = test * length
print 'test list outside function: {}'.format(
timeit.timeit(stmt=test_01,
setup='from __main__ import test',
number=10000))
print 'test list inside function: {}'.format(
timeit.timeit('unique_01()',
setup='from __main__ import test, unique_01',
number=10000))
print 'test set outside function: {}'.format(
timeit.timeit(stmt=test_02,
setup='from __main__ import test',
number=10000))
print 'test set inside function: {}'.format(
timeit.timeit('unique_02()',
setup='from __main__ import test, unique_02',
number=10000))
print 'test itertools outside function: {}'.format(
timeit.timeit(stmt=test_03,
setup='from __main__ import test, ifilterfalse',
number=10000))
print 'test itertools inside function: {}'.format(
timeit.timeit('unique_03()',
setup='from __main__ import test, unique_03, ifilterfalse',
number=10000))
Code: Alles auswählen
$ python ./equal_items.py 10
test list outside function: 0.101276159286
test list inside function: 0.100987195969
test set outside function: 0.0632679462433
test set inside function: 0.0638370513916
test itertools outside function: 0.0752058029175
test itertools inside function: 0.0768110752106
$ python ./equal_items.py 100
test list outside function: 0.917196989059
test list inside function: 1.02419400215
test set outside function: 0.458462953568
test set inside function: 0.451676130295
test itertools outside function: 0.550910949707
test itertools inside function: 0.557126998901
$ python ./equal_items.py 1000
test list outside function: 9.1905798912
test list inside function: 9.39835596085
test set outside function: 4.34967303276
test set inside function: 4.43209385872
test itertools outside function: 5.34194898605
test itertools inside function: 5.87611699104
mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit )
@mutetella: ich werde gern ignoriert . Nochmal zum Mitlesen: Je länger die Ergebnisliste, desto schlechter schneidet die List-Variante gegenüber der Set-Version ab. Bei Deinen Tests mit 10, 100, 1000 wird aber die selbe Eingangsliste nur 10, 100 oder 1000 mal durchlaufen, die Ergebnisliste ist aber immer die selbe! Ein sinnvoller Test variiert die Anzahl der unterschiedlichen Elemente in der Eingangsliste nicht deren Länge. Dann hast Du nämlich nicht ein lineares Laufzeitverhalten für alle Varianten, sondern bei gleich Listenlänge konstante Laufzeit bei "Set" und lineare bei "List".
@mutetella:
Ersetz doch mal Dein `test` durch so etwas und spiel mal mit dem hinteren Rangewert
Wenn Du Dir überlegst, wie Sets und Listen intern ticken, wird auch klar, was da passiert - die angefragten Operationen (suchen, einfügen) haben verschiedene Laufzeiten in der O-Notation und unterschiedliche Kosten für eine Einzeloperation. Z.B. ist Hashen+Suche im Hashbaum zunächst erstmal teuerer als Suche in einer Liste, eben weil Hashen aufwändig ist. Da die Suche in der Liste aber eine schlechtere Laufzeit hat, gibt es einen break-even point - für alle größeren n gewinnt immer der Hashansatz.
Ersetz doch mal Dein `test` durch so etwas und spiel mal mit dem hinteren Rangewert
Code: Alles auswählen
test = [''.join(random.choice(string.ascii_letters) for _ in range(3)) for _ in range(200)]
@Sirius3
Ich hab' Deine Erklärung nicht ignoriert. Ich verstehe nur den Zusammenhang zwischen `test` und der Ergebnisliste noch nicht. Wenn ich die Zufallsliste aus jerchs Beispiel verwende und mit einer multiplizierten Liste vergleiche...... dann hab' ich unter Verwendung der Zufallsliste wahrscheinlich weniger Duplikate, sprich' eine potentiell größere Ergebnisliste.
Also nicht, dass ich euch nicht glauben würde, zumal die Testergebnisse dasselbe ausdrücken...
Ich verstehe sehr wohl, dass bei einer umso größeren Ergebnisliste die set-Lösung performanter wird...
Ok, ich glaub' ich hab's geschnallt: Das Problem war nicht, dass jeder Test dieselbe Liste abarbeitete, sondern dass durch die einfache Multiplikation der Eingangsliste letztlich die Ergebnisliste doch dieselbe blieb und dadurch die Listenlösung niemals in den Bereich vordrang, ab dem sie ihren Vorteil gegenüber der Setlösung verlor. Kann man das so sagen?
mutetella
Ich hab' Deine Erklärung nicht ignoriert. Ich verstehe nur den Zusammenhang zwischen `test` und der Ergebnisliste noch nicht. Wenn ich die Zufallsliste aus jerchs Beispiel verwende und mit einer multiplizierten Liste vergleiche...
Code: Alles auswählen
>>> ['aFy', 'Dab', 'HZT'] * 2
['aFy', 'Dab', 'HZT', 'aFy', 'Dab', 'HZT']
>>> [''.join(random.choice(string.ascii_letters) for _ in range(3)) for _ in range(6)]
['xyi', 'erR', 'dew', 'oTU', 'aYF', 'KKO']
Aber sowohl mit der Zufalls- wie auch mit der multiplizierten Liste ist doch die Ergebnisliste auch immer gleich groß?Sirius3 hat geschrieben:Bei Deinen Tests mit 10, 100, 1000 wird aber die selbe Eingangsliste nur 10, 100 oder 1000 mal durchlaufen, die Ergebnisliste ist aber immer die selbe!
Also nicht, dass ich euch nicht glauben würde, zumal die Testergebnisse dasselbe ausdrücken...
Code: Alles auswählen
if __name__ == '__main__':
length = int(sys.argv[1])
test = [
''.join(random.choice(ascii_letters) for
_ in range(3)) for _ in range(length)
]
print 'test list outside function: {}'.format(
timeit.timeit(stmt=test_01,
setup='from __main__ import test',
number=10000))
print 'test list inside function: {}'.format(
timeit.timeit('unique_01()',
setup='from __main__ import test, unique_01',
number=10000))
print 'test set outside function: {}'.format(
timeit.timeit(stmt=test_02,
setup='from __main__ import test',
number=10000))
print 'test set inside function: {}'.format(
timeit.timeit('unique_02()',
setup='from __main__ import test, unique_02',
number=10000))
print 'test itertools outside function: {}'.format(
timeit.timeit(stmt=test_03,
setup='from __main__ import test, ifilterfalse',
number=10000))
print 'test itertools inside function: {}'.format(
timeit.timeit('unique_03()',
setup='from __main__ import test, unique_03, ifilterfalse',
number=10000))
Code: Alles auswählen
$ python ./equal_items.py 10
test list outside function: 0.0219969749451
test list inside function: 0.0241479873657
test set outside function: 0.0340809822083
test set inside function: 0.0344898700714
test itertools outside function: 0.0381298065186
test itertools inside function: 0.0383148193359
$ python ./equal_items.py 100
test list outside function: 0.745640993118
test list inside function: 0.752784013748
test set outside function: 0.312932014465
test set inside function: 0.304243803024
test itertools outside function: 0.329273939133
test itertools inside function: 0.340594768524
$ python ./equal_items.py 1000
test list outside function: 62.3739390373
test list inside function: 62.4985778332
test set outside function: 2.74161219597
test set inside function: 2.68796682358
test itertools outside function: 2.98557090759
test itertools inside function: 3.06113815308
Ok, ich glaub' ich hab's geschnallt: Das Problem war nicht, dass jeder Test dieselbe Liste abarbeitete, sondern dass durch die einfache Multiplikation der Eingangsliste letztlich die Ergebnisliste doch dieselbe blieb und dadurch die Listenlösung niemals in den Bereich vordrang, ab dem sie ihren Vorteil gegenüber der Setlösung verlor. Kann man das so sagen?
mutetella
Entspanne dich und wisse, dass es Zeit für alles gibt. (YogiTea Teebeutel Weisheit )
ja es ist ein datei die ich durch diese programm geöffnet habe.guy12 hat geschrieben:Hallo ich habe ein frage: ich habe ein Datei oder liste dt=["DK"
"D14"
"D34"
"D14"
"D34"
"D50"
"D81"
"D81"
"D91"
"D91"]
wie kann ich machen mit der Python programm sodass für jede element ich nur eine erhalte , ich meine dt =["Dk","D34","D14","D50","D81","D91"]
Danke im voraus
Code: Alles auswählen
with open("kurz-ergebnis.csv", "r") as fd:
for line in fd:
splitline=line.split(',');
print splitline[2]
fd.close()
weiss ich nicht
Zuletzt geändert von Hyperion am Freitag 30. Mai 2014, 12:39, insgesamt 1-mal geändert.
Grund: Code in Python-Code Tags gesetzt.
Grund: Code in Python-Code Tags gesetzt.
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Bitte benutze als Einrückung vier Leerzeichen anstelle eines Tabulators! (PEP8 sieht das so vor und man kann das in jedem guten Editor einstellen, dass dieser bei Druck auf Tab vier Leerzeichen in das Dokument übernimmt - es ist also *nicht* mehr Tipparbeit)
Das ``fd.close`` ist obsolete, da Du die Datei mittels ``with`` öffnest!
Wo genau hakt es denn? Was steht denn jeweils in ``splitline``?
Das ``fd.close`` ist obsolete, da Du die Datei mittels ``with`` öffnest!
Wo genau hakt es denn? Was steht denn jeweils in ``splitline``?
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert