Aus einer Liste doppelte Einträge entfernen (Einzeiler)

Code-Stücke können hier veröffentlicht werden.
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Beitragvon Milan » Sonntag 12. Dezember 2004, 19:17

*hehe*, das kommt schon noch :wink: Die schönste und resourcenspaarenste ist die von Voges auf 2.4 übersetzt. Bei der bleibt dann die Sortierung auch erhalten, was sehr vorteilhaft sein kann. Deswegen nehm ich weder dicts noch sets (welche ja auch nur dicts mit speziellen Methoden sind)

Code: Alles auswählen

(item for (i,item) in enumerate(longList) if item not in longList[:i])

Dumm nur, das longList selbst kein Iterator sein kann, da die kein slicing unterstützen.
Clython
User
Beiträge: 151
Registriert: Samstag 21. August 2004, 13:58
Wohnort: Schweiz, BE-2500

Beitragvon Clython » Sonntag 12. Dezember 2004, 19:29

Tja mir ist im nachhinein aufgefallen, dass ich so dumm gar nicht bin, da mein Code die Liste flattet aber gleichzeitig auch das Vorkommen der einzelnen Tokens zählt (brauchte den Algorithmus für meinen Tokenizer). Hier mal der Code, Verbesserungsvorschläge gerne gesehen:

Code: Alles auswählen

def count_words(liste):
   liste.sort()
   current_pos = 0
   first_pos = 0
   out_liste = []
   nr_liste = []
   list_length = len(liste)
   word = liste[current_pos]
   while current_pos <= list_length:
      if current_pos < list_length:
         new_word = liste[current_pos]
         if word != new_word:
            last_pos = current_pos - 1
            anzahl_vorkommen = last_pos - first_pos
            out_liste.insert(0, word)
            nr_liste.insert(0, [word, anzahl_vorkommen + 1])
            first_pos = current_pos
            word = liste[current_pos]
      else:
         last_pos = current_pos - 1
         anzahl_vorkommen = last_pos - first_pos
         out_liste.insert(0, word)
         nr_liste.insert(0, [word, anzahl_vorkommen + 1])
      current_pos = current_pos + 1
   out_liste.reverse()
   nr_liste.reverse()
   return out_liste, nr_liste, list_length

Edit by Dookie: Code in Pythontags gesetzt
Benutzeravatar
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Beitragvon Dookie » Sonntag 12. Dezember 2004, 19:51

hier mal meine Version, unter Einbeziehung vorhandener Lösungen.

Code: Alles auswählen

def count_words2(liste):
    out_liste = [item for (i,item) in enumerate(liste) if item not in liste[:i]]
    nr_liste = [[item, liste.count(item)] for item in out_liste]
    list_length = len(liste)
    return out_liste, nr_liste, list_length


Gruß

Dookie

Code: Alles auswählen

#!/usr/bin/env python
import this
joe

Beitragvon joe » Sonntag 12. Dezember 2004, 20:03

Auch wenn ich nicht ganz verstaqnden habe, was cpythons count_words leisten soll:

Code: Alles auswählen

def count_words3(liste):
    wc = {}
    for w in liste:
        wc[w] = 1 + wc.get(w,0)
    return wc.keys(),wc.items(),len(liste)

Das resultat ist zumindest sehr ähnlich.
joe
Benutzeravatar
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Beitragvon Dookie » Sonntag 12. Dezember 2004, 20:16

ich hab auch noch eine Alternative, diesmal mit Set.

Code: Alles auswählen

from sets import Set # für Pythonversion < 2.4

def count_words3(liste):
    nr_liste = [[item, liste.count(item)] for item in Set(liste)]
    out_liste = [item for item, nr in nr_liste]
    list_length = sum([nr for item, nr in nr_liste])
    return out_liste, nr_liste, list_length


Gruß

Dookie

Code: Alles auswählen

#!/usr/bin/env python
import this
joe

Beitragvon joe » Sonntag 12. Dezember 2004, 20:39

Etwas "umformuliert":

Code: Alles auswählen

from sets import Set
def count_words3(liste):
    out_liste = list(Set(liste))
    nr_liste = [(w,liste.count(w)) for w in out_liste]
    return out_liste, nr_liste, len(liste)

joe
Benutzeravatar
Leonidas
Administrator
Beiträge: 16023
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Beitragvon Leonidas » Sonntag 12. Dezember 2004, 21:20

Ihr seit aber schon ziemlich offtopic, Dookie selbst hat im letzten Post sechs Zeilen zu viel gehabt ;)
My god, it's full of CARs! | Leonidasvoice vs Modvoice
Benutzeravatar
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Beitragvon Dookie » Sonntag 12. Dezember 2004, 21:44

um zu Clythons Version zurückzukommen, hab ich die auch mal etwas optimiert.

Code: Alles auswählen

def count_words4(liste):
    liste.sort()
    first_pos = 0
    current_pos = 0
    out_liste = []
    nr_liste = []
    list_length = len(liste)
    if not list_length: # nothing to do
        return out_liste, nr_liste, list_length
    word = liste[0]
    for current_pos in xrange(1, list_length):
        new_word = liste[current_pos]
        if word != new_word:
            last_pos = current_pos - 1
            anzahl_vorkommen = last_pos - first_pos
            out_liste.append(word)
            nr_liste.append([word, anzahl_vorkommen + 1])
            first_pos = current_pos
            word = new_word
    else:
        last_pos = current_pos
        anzahl_vorkommen = last_pos - first_pos
        out_liste.append(word)
        nr_liste.append([word, anzahl_vorkommen + 1])
    return out_liste, nr_liste, list_length


1. und auffälligste Änderung, statt einer Whileschleife und hochzählen einer variable mit var += 1 ist eine Forschleife mit xrange effektiver. Hier kann mit 1 begonnen werden, da das erste Wort ohnehin schon vor der Schleife ausgelesen wird.
2. Verwendung von else bei der Forschleife. Das Else wird ausgeführt, wenn die Schleife fertig durchlaufen wurde. Erspart eine if-Abfrage in der Schleife.
3. statt word = liste[current_pos] ist es effektiver auf die lokale Variable new_word mit word = new_word zuzugreifen.
4. verwendung von list.append(word) statt list.insert(0,word), spart auch das list.reverse() am Ende.

Das Ganze ist auch als Anregung gedacht für allgemeine Optimierungen.


Gruß

Dookie

Code: Alles auswählen

#!/usr/bin/env python
import this
Milan
User
Beiträge: 1078
Registriert: Mittwoch 16. Oktober 2002, 20:52

Beitragvon Milan » Montag 13. Dezember 2004, 19:30

Hi. Naja, ist ja auch klar, dass das ganze schneller wird, wenn man mit mehreren Variablen arbeitet. Aber gefragt waren ja Einzeiler gefragt, sonst optimieren wir uns noch in den negativen Bereich :wink:

Btw: wieso verwendest du nochmal else? Der Teil wird in jedem Fall ausgeführt, da in der Schleife kein break steht...
Benutzeravatar
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Beitragvon Dookie » Montag 13. Dezember 2004, 19:37

jo dat läuft auch ohne else, aber so ists IMHO besser ersichtlich, daß der Teil eigentlich noch zur Schleife gehört und tut der Effizienz keinen Abbruch.


Gruß

Dookie

Code: Alles auswählen

#!/usr/bin/env python
import this
Gast

Beitragvon Gast » Freitag 14. Januar 2005, 13:51

Hallo,

ich bräuchte auch so etwas nur das meine liste listen mit 2 elementen enthält:

l =[['a', 8], ['b', 7], ['a', 8], ['a', 9], ['c', 6], ['b', 2]]

es soll alle doppeleten l[x][0] entfernen elemente,
also nur ein, b, und c stehen lassen, und dabei nur die ersten vorkommen.
das heisst, das 'a' ist dreimal enthalten, das erste vorkommen ['a', 8]
soll behalten werden und die Sortierung idealerweise auch.

nach reduzieren:
also:
[['a', 8], ['b', 7], ['c', 6]]
Benutzeravatar
Dookie
Python-Forum Veteran
Beiträge: 2010
Registriert: Freitag 11. Oktober 2002, 18:00
Wohnort: Salzburg
Kontaktdaten:

Beitragvon Dookie » Freitag 14. Januar 2005, 14:49

Hi gast,

im Prinzip müsstest du beim obigen Script nur die Zeile mit dem if so ändern das word[0] mit new_word[0] verglichen wird, allerdings bleibt dann deine Sortierung nicht bestehen.

Hier eine spezialisierte Funktion:

Code: Alles auswählen

def deldoub1(liste):
    res = []
    tmp = []
    for item in liste:
        if not item[0] in tmp:
            tmp.append(item[0])
            res.append(item)
    return res


Gruß

Dookie

Code: Alles auswählen

#!/usr/bin/env python
import this
Gast

Beitragvon Gast » Donnerstag 20. Januar 2005, 17:32

Dookie hat geschrieben:Hi gast,

im Prinzip müsstest du beim obigen Script nur die Zeile mit dem if so ändern das word[0] mit new_word[0] verglichen wird, allerdings bleibt dann deine Sortierung nicht bestehen.

Hier eine spezialisierte Funktion:

Code: Alles auswählen

def deldoub1(liste):
    res = []
    tmp = []
    for item in liste:
        if not item[0] in tmp:
            tmp.append(item[0])
            res.append(item)
    return res


Gruß

Dookie


Danke, eigentlich gar nicht so schwierig :roll:

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder