2016-10-11 5 views
0

У меня есть два списка. Сначала один выглядит следующим образом:Nuke Python список объектов заказать по иному списку

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

, а другой представляет собой список объектов, - в этом случае Nuke узлы:

nodes = nuke.selectedNodes() 

Я пытаюсь сравнить параметр имени каждого узла со списком passOrder и расположите их в порядке, указанном в passOrder. Я попытался явно настроить indexndode index, но я думаю, что это невозможно, когда список пуст при запуске.

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

Я также попытался закрепить оба списка и отсортировать их - здесь не повезло. В принципе, я понятия не имею, как перебирать компонент n['name'].value() при сортировке.

ответ

2

Я не знаю, что ваши определения класса/функции выглядеть, поэтому я использую эти корешки, чтобы проиллюстрировать мое решение:

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")] 

Можно сортировать nodes, используя passOrder.index для ключевого параметра:

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 

Результат:

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

Вы можете построить словарь отображение узлов имен узлов, как этот

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

С помощью этого словаря, это тривиально, чтобы получить узлы в нужном порядке:

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

Если бы имена в passOrder без соответствующих узлов, вы можете просто пропустить их:

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

Этот подход более простой и эффективный, чем попытка сортировки.

1

Вам не нужно кодировать сортировку самостоятельно.

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

Это предпочтительнее, чем мое решение, если возможно, что 'nodes' будет содержать Nuke, имя которого не находится в' passOrder'. Хорошая защитная кодировка. – Kevin

+0

@Kevin Спасибо! Фактически я видел ваше решение после того, как я разместил свой. –

+0

@S. de Melo Спасибо за такое элегантное решение. Я пытаюсь ввести регулярное выражение в эту функцию для соответствия имени слоев, которое начинается с строк, заданных в passOrder, например. 'Direct_diffuse_layerName_2'. –