2016-10-11 3 views
0

두 목록이 있습니다.Nuke Python 다른 목록을 기반으로하는 개체 순서

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

을하고 다른 하나는 객체의 목록입니다 -이 경우 핵무기 노드 : 첫 번째는 다음과 같습니다

nodes = nuke.selectedNodes() 

내가 passOrder 목록과 각 노드의 이름 매개 변수를 비교하기 위해 노력하고있어 passOrder에 주어진 순서대로 정렬하십시오. 명시 적으로 orderedNodes 인덱스를 설정하려했지만 시작시 목록이 비어 있으면 불가능하다고 생각합니다.

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

나는 또한 두 목록을 압축하고 정렬하려고 시도했다. 기본적으로 정렬 할 때 n['name'].value() 구성 요소를 반복하는 방법을 알지 못합니다.

답변

2

나는 클래스/함수 정의가 어떻게 생겼는지 모르는, 그래서 난 내 솔루션을 설명하기 위해이 스텁을 사용하고 있습니다 : 주요 매개 변수 passOrder.index를 사용하여,

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 = [ 
        '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 '에'passOrder'에 이름이없는 Nuke가 포함될 가능성이있는 경우이 방법이 내 솔루션보다 바람직합니다. 좋은 방어 코딩. – Kevin

+0

@ 케빈 고마워! 사실 내가 게시 한 후에 귀하의 솔루션을 보았습니다. –

+0

@S. de Melo 그런 우아한 해결책에 감사드립니다. 나는 예를 들면, passOrder에 주어진 문자열로 시작하는 레이어 이름과 일치하도록이 기능으로 정규식을 주입하기 위해 노력하고있어 'direct_diffuse_layerName_2 '. –

관련 문제