index in tupel/list finden

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
joh#
User
Beiträge: 139
Registriert: Freitag 6. November 2009, 13:16

Hallo,

ich möchte die Position mehrerer Zahlen in einem Tupel oder einer List
ermitteln (Methode index()) Allerdings kann es auch vorkommen, daß
die gesuchte Zahl gar nicht vorhanden ist, die dann geworfene exception
ValueError habe ich durch entsprechende Schachtelung entschärft, aber
(Laufzeit-) optimal finde ich das nicht:

Code: Alles auswählen

ist=(2,5,6,7,8,12,13)


try:
    print ist.index(9)
except ValueError:
    try:
        print ist.index(4)
    except ValueError:
        try:
            print ist.index(14)
        except:
            print 'gibts nicht'
Hat jemand vielleicht eine bessere/schnellere Lösung?

Gruß
joh
.robert
User
Beiträge: 274
Registriert: Mittwoch 25. April 2007, 17:59

morgen (gäääähhhhnnn),

Code: Alles auswählen

ist=[2,5,6,7,8,12,13]

if 9 in ist:
    print ist.index(9)
else:
    print "WHHHhoooaaaa, oh nein, fuck!"
und: tupel haben keine "index" Funktion!
joh#
User
Beiträge: 139
Registriert: Freitag 6. November 2009, 13:16

.robert hat geschrieben:morgen (gäääähhhhnnn),

...und: tupel haben keine "index" Funktion!
mmhhh... und wieso läuft dann mein code s.o.? (ist Python 2.6)
.robert
User
Beiträge: 274
Registriert: Mittwoch 25. April 2007, 17:59

joh# hat geschrieben:mmhhh... und wieso läuft dann mein code s.o.? (ist Python 2.6)
Weil du mit dem letzten except alle Fehler abfängst!

Mach mal ein positiv-beispiel, also so:

Code: Alles auswählen

In [4]: a = (2,3)

In [5]: a.index(2)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)

C:\Dokumente und Einstellungen\******\<ipython console> in <module>()

AttributeError: 'tuple' object has no attribute 'index'

Edit: wieder ein super Beispiel, warum man keine leeren except-definitionen machen sollte!
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

joh# hat geschrieben:
.robert hat geschrieben:morgen (gäääähhhhnnn),

...und: tupel haben keine "index" Funktion!
mmhhh... und wieso läuft dann mein code s.o.? (ist Python 2.6)
Weil Tupel in 2.6 eine index-Funktion haben, lass dich nicht verwirren :)

@robert: Das stimmt nicht das letzte except fängt nur alle Exceptions des letzten trys, aber nicht alle der ersten beiden.
.robert
User
Beiträge: 274
Registriert: Mittwoch 25. April 2007, 17:59

oh, das 2.6 habe ich übersehen (und ich sollte dringend hier mal ein update machen auch 2.6)

Sorry dafür...
BlackJack

@joh#: Deinen Ursprungscode kann man ohne die Verschachtelung so schreiben:

Code: Alles auswählen

ist = [2, 5, 6, 7, 8, 12, 13]

for needle in [9, 4, 14]:
    try:
        print ist.index(needle)
        break
    except ValueError:
        pass    # Ignored intentionally.
else:
    print 'gibts nicht'
Das ganze bei gleicher Semantik effizienter zu schreiben führt zu relativ komplexem Quelltext. Zumindest falls ich da nichts einfacheres übersehen habe. Das würde ich nur machen, wenn das hier wirklich zu langsam sein sollte.
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Ich würde es warscheinlich so machen:

Code: Alles auswählen

In [18]: l
Out[18]: [2, 5, 6, 7, 8, 12, 13]

In [19]: indexes = dict((x, l.index(x)) for x in [9, 3, 14] if x in l)

In [20]: indexes
Out[20]: {}

In [21]: indexes = dict((x, l.index(x)) for x in [9, 13, 14] if x in l)

In [22]: indexes
Out[22]: {13: 6}
Sofern man wissen will ob und für welchen Wert welcher Index existiert.
BlackJack

@Zap: Das ist aber noch ineffizienter als der Quelltext von mir und vom OP weil das ``x in l`` auch nochmal linear in der Liste sucht -- etwas was die `index()`-Methode doch auch schon tut.
Zap
User
Beiträge: 533
Registriert: Freitag 13. Oktober 2006, 10:56

Mir ging es nur darum das man die gesammelten Daten auch irgendwie weiter verwenden kann. Ich hätte keine LC verwenden können da ".index" leider nur mit einem IndexError aussteigt und keinen default wert kennt.
Bei der hier angegebenen Menge an Daten fällt diese ineffizienz nicht wirklich ins Gewicht. Ist aber gut das du darauf hinweist ;)
joh#
User
Beiträge: 139
Registriert: Freitag 6. November 2009, 13:16

Zap hat geschrieben:Bei der hier angegebenen Menge an Daten fällt diese ineffizienz nicht wirklich ins Gewicht. Ist aber gut das du darauf hinweist ;)
naja, wenn die function 800k mal aufgerufen wird dann schon...
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

joh# hat geschrieben:Hat jemand vielleicht eine bessere/schnellere Lösung?
Evtl. lässt sich eine schnellere Lösung ohne größeren Aufwand implementieren. Das hängt u.a. davon ob, wie groß der Wertebereich deines Tupels ist. Wichtig zu wissen wäre auch, ob du immer wieder nach unterschiedlichen Werten im selben Tupel suchst, oder jeder Suchvorgang sich auf ein anderes Tupel bezieht, in dem gesucht wird.

Und: Wo kommen die Daten denn her? Evtl. lässt sich bei der Erzeugung der Daten schon etwas machen.
Benutzeravatar
gkuhl
User
Beiträge: 600
Registriert: Dienstag 25. November 2008, 18:03
Wohnort: Hong Kong

Ergänzende Frage: Wie lang sind deine Listen? Bei sehr vielen Daten ist ``dict.has_key`` deutlich schneller als ``list.index``. Ansonsten kann man auch ``numpy.array`` verwenden. Hängt davon ab, was du eigentlich vor hast.

Grüße
Gerrit
Dav1d
User
Beiträge: 1437
Registriert: Donnerstag 30. Juli 2009, 12:03
Kontaktdaten:

gkuhl hat geschrieben:(...) Bei sehr vielen Daten ist ``dict.has_key`` deutlich schneller als (...)
Du meinst

Code: Alles auswählen

key in dict
In Python 3 gibt es kein "has_key"
the more they change the more they stay the same
joh#
User
Beiträge: 139
Registriert: Freitag 6. November 2009, 13:16

gkuhl hat geschrieben:Ergänzende Frage: Wie lang sind deine Listen? ...
Gerrit
Das Tupel ist in diesem Fall nur 3 Elemente lang, wobei für jedes Element nur 4 Zahlenwerte
möglich sind, hält sich also alles in Grenzen. Werden soll es eine "Alpha/Betha-Suche" über
1.728.000 Kombinationen im worst case
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Falls dir immer noch daran gelegen ist, dass andere dir behilflich sein sollen, dass dein Algorithmus schneller wird, dann musst du präzisere Angaben machen.
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

Vielleicht lohnt es sich, über ein Set zu gehen:

Code: Alles auswählen

tup = (2,5,6,7,8,12,13)
for x in set((9,4,14)).intersection(tup):
    print tup.index(x)
Bei dieser Herangehensweise weiß man aber natürlich nur, ob es Fundstellen gibt und man kennt die Positionen, man weiß aber nicht, welche Zahl wo gefunden wurde. Es bleibt weiterhin die Frage offen, was genau du vor hast. Oder ist das ein Geheimnis? Vielleicht gibt es einen wesentlich effizienteren Algorithmus für dein Problem.
Benutzeravatar
snafu
User
Beiträge: 6731
Registriert: Donnerstag 21. Februar 2008, 17:31
Wohnort: Gelsenkirchen

joh# hat geschrieben:Das Tupel ist in diesem Fall nur 3 Elemente lang, wobei für jedes Element nur 4 Zahlenwerte
möglich sind, hält sich also alles in Grenzen.
Ist damit also sowas gemeint?

Code: Alles auswählen

values = [(1,2,3), (2,3,4), (3,4,1)]
wanted = set([4,1,2])
Oder heißt die Angabe, dass die 3 Elemente 4 verschieden Werte aus dem Bereich von bspw. 1-50 haben?

Code: Alles auswählen

values = [(34,12,45,1), (4,8,23,16), (50,33,34,2)]
Irgendwie deckt sich das aber alles nicht mit dem eingangs gemachten Beispiel von dir. Also, was willst du genau? Weißt du überhaupt, was du willst? ;)
joh#
User
Beiträge: 139
Registriert: Freitag 6. November 2009, 13:16

@numerix, snafu
snafu hat geschrieben:Vielleicht lohnt es sich, über ein Set zu gehen:
. . .
Oder ist das ein Geheimnis? .
[[na google/Schäuble&Co schlafen wohl noch ... :) ]]
Ich hab doch in einem anderen Beitrag schon mal nach einem
Skat Problem angefragt...
Was ich also letztlich (verstehen) will, wie man für jede Möglichkeit des
Spielverlaufs ab Stich 6 (das sind die erwähnten 1728000) die
für die jeweiligen Spieler eingebrachten Augensummen berechnet,
nätürlich mit dem Ziel, die richtige Karte auszuwählen.
Und dazu muß natürlich irgendwann mal der Besitzer des jeweiligen
Stichs ermittelt werden.

snafu hat geschrieben: Vielleicht gibt es einen wesentlich effizienteren Algorithmus für dein Problem
bis jetzt existiert eine liste mit allen möglichen Kombnationen s.o., mit Referenzen auf die aktuelle Kartensituation.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Wenn du dir einmal die Mühe machen würdest, exakt zu benennen, wie viele verschiedene und welche Werte in wie vielen verschiedenen Tupeln welcher Länge und mit welchen minimalen und maximalen Werten zu suchen sind, würde das die Chance, dass noch jemand eine Idee zur Performance-Steigerung hat, enorm erhöhen.
Antworten