Seite 1 von 2

Verfasst: Sonntag 12. Dezember 2004, 19:17
von Milan
*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.

Verfasst: Sonntag 12. Dezember 2004, 19:29
von Clython
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

Verfasst: Sonntag 12. Dezember 2004, 19:51
von Dookie
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

Verfasst: Sonntag 12. Dezember 2004, 20:03
von joe
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

Verfasst: Sonntag 12. Dezember 2004, 20:16
von Dookie
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

Verfasst: Sonntag 12. Dezember 2004, 20:39
von joe
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

Verfasst: Sonntag 12. Dezember 2004, 21:20
von Leonidas
Ihr seit aber schon ziemlich offtopic, Dookie selbst hat im letzten Post sechs Zeilen zu viel gehabt ;)

Verfasst: Sonntag 12. Dezember 2004, 21:44
von Dookie
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

Verfasst: Montag 13. Dezember 2004, 19:30
von Milan
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...

Verfasst: Montag 13. Dezember 2004, 19:37
von Dookie
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

Verfasst: Freitag 14. Januar 2005, 13:51
von Gast
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]]

Verfasst: Freitag 14. Januar 2005, 14:49
von Dookie
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

Verfasst: Donnerstag 20. Januar 2005, 17:32
von Gast
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: