Seite 1 von 2

index in tupel/list finden

Verfasst: Dienstag 23. März 2010, 08:52
von joh#
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

Verfasst: Dienstag 23. März 2010, 09:19
von .robert
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!

Verfasst: Dienstag 23. März 2010, 10:03
von joh#
.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)

Verfasst: Dienstag 23. März 2010, 10:06
von .robert
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!

Verfasst: Dienstag 23. März 2010, 10:10
von Darii
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.

Verfasst: Dienstag 23. März 2010, 10:14
von .robert
oh, das 2.6 habe ich übersehen (und ich sollte dringend hier mal ein update machen auch 2.6)

Sorry dafür...

Verfasst: Dienstag 23. März 2010, 10:22
von 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.

Verfasst: Dienstag 23. März 2010, 10:29
von Zap
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.

Verfasst: Dienstag 23. März 2010, 11:12
von 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.

Verfasst: Dienstag 23. März 2010, 12:37
von Zap
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 ;)

Verfasst: Dienstag 23. März 2010, 15:40
von joh#
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...

Re: index in tupel/list finden

Verfasst: Dienstag 23. März 2010, 16:18
von numerix
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.

Verfasst: Dienstag 23. März 2010, 18:28
von gkuhl
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

Verfasst: Dienstag 23. März 2010, 19:36
von Dav1d
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"

Verfasst: Dienstag 23. März 2010, 21:24
von joh#
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

Verfasst: Dienstag 23. März 2010, 21:40
von numerix
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.

Verfasst: Mittwoch 24. März 2010, 06:45
von snafu
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.

Verfasst: Mittwoch 24. März 2010, 07:07
von snafu
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? ;)

Verfasst: Mittwoch 24. März 2010, 10:21
von joh#
@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.

Verfasst: Mittwoch 24. März 2010, 15:42
von numerix
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.