Element in Sequenz finden und rotieren

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.
calo
User
Beiträge: 38
Registriert: Freitag 8. Dezember 2006, 21:35
Wohnort: Stuttgart

Element in Sequenz finden und rotieren

Beitragvon calo » Donnerstag 27. September 2007, 05:58

Hallo,

ich bin mir nicht sicher ob es auch besser geht. Jedenfalls sieht meine Lösung ziemlich umständlich aus. Ziel ist es eine Sequenz (in meinem Fall: Tuple in Tuple) solange zu rotieren bis ein Wertepaar, dass mit einem bestimmten Wert beginnt, an erster Stelle steht. Das Tuple mit den Wertepaaren könnte folgendermaßen aussehen:

Code: Alles auswählen

nodepairs = ((23, 14),(12, 13),(982,27893),(1233,37),(1,8123))


Im Falle, dass 982 die gesuchte Nummer ist, soll das Ergebnis so aussehen:

Code: Alles auswählen

np = ((982,27893),(1233,37),(1,8123),(23, 14),(12, 13))


In der Praxis sind das mehrere Tausend Wertepaare. Keine Nummer wiederholt sich dabei. Meine bisherige Lösung dazu:

Code: Alles auswählen

import scipy

def rot(seq, n=1):
    """rotates and returns the sequence seq
    """
    c = len(seq)
    if c == 0: return seq
    n = n % c
    return seq[n:] + seq[:n]

start_node = 982
start_pos = scipy.array(nodepairs).transpose().tolist()[0].index(start_node) + 1
np = rot(nodepairs, start_pos)


Meine Lösung funktioniert ja. Sieht aber unschön aus. Insbesondere Zeile 12. Darin wird das Wertepaar, dass mit start_node beginnt gesucht bzw dessen Index. Lässt sich diese Zeile auch irgendwie eleganter lösen?

Grüßle, Calo
Benutzeravatar
Rebecca
User
Beiträge: 1662
Registriert: Freitag 3. Februar 2006, 12:28
Wohnort: DN, Heimat: HB
Kontaktdaten:

Beitragvon Rebecca » Donnerstag 27. September 2007, 08:29

Ich finde das hier besser:

Code: Alles auswählen

def rot(seq, search):
    for (i, item) in enumerate(seq):
        if item[0] == search: break
    else:
        raise ValueError("%s not in sequence." % search)

    return seq[i:] + seq[:i]


Code: Alles auswählen

>>> nodepairs = ((23, 14),(12, 13),(982,27893),(1233,37),(1,8123))
>>> rot(nodepairs, 982)
((982, 27893), (1233, 37), (1, 8123), (23, 14), (12, 13))
>>> rot(nodepairs, 14)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "test.py", line 7, in rot
    raise ValueError("%s not in sequence." % search)
ValueError: 14 not in sequence.
Offizielles Python-Tutorial (Deutsche Version)

Urheberrecht, Datenschutz, Informationsfreiheit: Piratenpartei
BlackJack

Beitragvon BlackJack » Donnerstag 27. September 2007, 10:03

Und noch eine Variante mit etwas generischerer `index()` und `rotated()` Funktionen:

Code: Alles auswählen

from itertools import imap
from operator import itemgetter


def index(iterable, needle, key=lambda x: x):
    for i, item in enumerate(imap(key, iterable)):
        if needle == item:
            return i
    raise ValueError('nothing found')


def rotated(sequence, amount=1):
    if not (sequence or amount):
        return sequence
    return sequence[amount:] + sequence[:amount]


def main():
    node_pairs = ((23, 14), (12, 13), (982, 27893), (1233, 37), (1, 8123))
    position = index(node_pairs, 982, itemgetter(0))
    node_pairs = rotated(node_pairs, position)
    print node_pairs
Y0Gi
User
Beiträge: 1454
Registriert: Freitag 22. September 2006, 23:05
Wohnort: ja

Beitragvon Y0Gi » Donnerstag 27. September 2007, 11:57

Bei "rotieren" muss ich sofort an `collections.deque` denken, eine doppelt verkettete Liste mit schneller Rotationsoperation. Das kommt vielleicht für dich in Frage.
calo
User
Beiträge: 38
Registriert: Freitag 8. Dezember 2006, 21:35
Wohnort: Stuttgart

Beitragvon calo » Donnerstag 27. September 2007, 16:10

Hallo,

vielen Dank für die Tipps :D

calo

Wer ist online?

Mitglieder in diesem Forum: brainstir