2016-10-11 5 views
0

Ich habe zwei Listen. Zuerst sieht wie folgt aus:Nuke Python Liste der Objekte Reihenfolge basierend auf anderen Liste

passOrder = [ 
        'direct_diffuse', 
        'direct_specular', 
        'direct_specular_2', 
        'indirect_diffuse', 
        'indirect_specular', 
        'indirect_specular_2', 
        'refraction', 
        'reflection', 
        'emission', 
        'sss' 
       ] 

und das andere ist eine Liste von Objekten - in diesem Fall Nuke Knoten:

nodes = nuke.selectedNodes() 

Ich versuche, jeden Knoten Name des Parameters mit passOrder Liste zu vergleichen und Ordne sie in der Reihenfolge an, die in passOrder angegeben ist. Ich habe versucht, den orderedNodes-Index explizit einzurichten, aber ich denke, es ist nicht möglich, wenn die Liste beim Start leer ist.

orderedNodes = [] 
for n in nodes: 
    for index, p in enumerate(passOrder): 
     if n['name'].value() == p: 
      orderedNodes.insert(index, n) 

Ich habe auch versucht, beide Listen zu zippen, und sortiere sie - kein Glück hier. Grundsätzlich habe ich keine Ahnung, wie man über n['name'].value() Komponente beim Sortieren iteriert.

Antwort

2

Ich weiß nicht, was Ihre Klasse/Funktionsdefinitionen aussehen, so dass ich diesen Stubs mit meiner Lösung erläutern:

class Thing: 
    def __init__(self, value): 
     self.val = value 
    def value(self): 
     return self.val 

class Nuke: 
    def __init__(self, name): 
     self.n = {"name": Thing(name)} 
    def __repr__(self): 
     return "Node({})".format(repr(self.n["name".value())) 

def selectedNodes(): 
    return [Nuke("refraction"), Nuke("direct_diffuse"), Nuke("emission")] 

Sie nodes sortieren könnten, passOrder.index für seine wichtigsten Parameter verwendet:

passOrder = [ 
        'direct_diffuse', 
        'direct_specular', 
        'direct_specular_2', 
        'indirect_diffuse', 
        'indirect_specular', 
        'indirect_specular_2', 
        'refraction', 
        'reflection', 
        'emission', 
        'sss' 
       ] 

nodes = selectedNodes() 
nodes.sort(key=lambda item: passOrder.index(item.n["name"].value())) 
print nodes 

Ergebnis:

[Node('direct_diffuse'), Node('refraction'), Node('emission')] 
0

Sie können einem Wörterbuch-Mapping Knotennamen zu Knoten wie dieses

nodes_by_name = {n['name'].value(): n for n in nodes} 

Mit diesem Wörterbuch konstruieren, ist es trivial, die die Knoten in der gewünschten Reihenfolge abzurufen:

ordered_nodes = [nodes_by_name[name] for name in passOrder] 

Wenn es könnten Namen in passOrder sein Knoten ohne entsprechen, Sie können sie einfach überspringen:

Dieser Ansatz ist einfacher und effizienter als der Versuch, die Sortierung zu verwenden.

1

Sie müssen die Sortierung nicht selbst codieren.

ordered_nodes = sorted(nodes, key=lambda n: passOrder.index(n["name"].value()) if n["name"].value() in passOrder else len(passOrder)) 
+0

Dies ist meiner Lösung vorzuziehen, wenn es möglich ist, dass 'nodes' einen Nuke enthält, dessen Name nicht in' passOrder' steht. Nette defensive Codierung. – Kevin

+0

@Kevin Danke! Tatsächlich habe ich deine Lösung gesehen, nachdem ich meine veröffentlicht habe. –

+0

@S. de Melo Danke für diese elegante Lösung. Ich versuche, Regex in diese Funktion zu injizieren, um Layernamen, die mit Strings beginnen, die in passOrder, z. 'direct_diffuse_layerName_2'. –

Verwandte Themen