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

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:

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

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

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: 52
Registriert: Freitag 8. Dezember 2006, 21:35
Wohnort: Stuttgart

Hallo,

vielen Dank für die Tipps :D

calo
Antworten