【问题标题】:Nuke Python list of objects order based on other listNuke Python 对象列表基于其他列表的顺序
【发布时间】:2017-02-20 00:42:31
【问题描述】:

我有两个列表。第一个看起来像这样:

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 中给出的顺序排列它们。我尝试显式设置orderedNodes 索引,但我想当列表在开始时为空时这是不可能的。

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

我还尝试压缩这两个列表,并对它们进行排序 - 这里没有运气。基本上我不知道在排序时如何迭代n['name'].value() 组件。

【问题讨论】:

    标签: python list sorting object nuke


    【解决方案1】:

    我不知道你的类/函数定义是什么样的,所以我使用这些存根来说明我的解决方案:

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

    【讨论】:

      【解决方案2】:

      您不必自己编写排序代码。

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

      【讨论】:

      • 如果nodes 可能包含一个名称不在passOrder 中的Nuke,这比我的解决方案更可取。很好的防御性编码。
      • @Kevin 谢谢!事实上,我在发布我的解决方案后看到了您的解决方案。
      • @S. de Melo 感谢您提供如此优雅的解决方案。我正在尝试将正则表达式注入此函数以匹配以 passOrder 中给出的字符串开头的图层名称,例如direct_diffuse_layerName_2.
      【解决方案3】:

      您可以像这样构造一个将节点名称映射到节点的字典

      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]
      

      这种方法比尝试使用排序更简单、更有效。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-09-24
        • 1970-01-01
        • 1970-01-01
        • 2020-11-30
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多