对列表的修改操作中,根据索引来进行数据替换是个非常常用的需求,实现也很简单,Dynamo内置节点就支持:List.ReplaceItemAtIndex。正常情况下,替换一个索引是没有问题的。
但是如果需要替换多个索引呢?
首先,可以引用并运行这个节点N次,实现N个索引的替换,一如在Dynamo For Revit中使用Element.GetParameterValueByName这个节点来获取Element的多个属性。但是这类节点的输入输出不是同一类型的数据,因此可以使用调整连缀的方式来实现一个节点获取多个属性的数据。具体可以参照应用秘籍1的介绍。
对于List.ReplaceItemAtIndex这个节点,情况就不一样了,首先,输入和输出的数据类型一致,同时,按照顺次调用的原则,中间节点的输入已经不是最原始的列表而是已经修改过部分索引的列表,因此是无法使用一个节点实现多个索引的替换的。即使我们尝试这么做,也会出错,如下面的截图所演示的:
返回值列表结构与输入列表的不一致,每个子列表仅替换了一个索引
这种情况下,即使尝试使用级别控制,也不能获取我们需要的结果:
这是什么原因呢?主要是因为List.ReplaceItemAtIndex节点的输入端口数据类型限定:
在item端口,Dynamo定义其缺省数据类型为多层列表“[]...[]”,因此无法为单独的数据类型如数字、字符串来进行替换。在替换多个索引时,节点会将Item的输入当成一个整体来顺次替换对应的索引,这也是为啥在上面的图片中,会发现结果的子列表层级关系都变了。
那么如何实现多个索引的替换呢?要真是变成复制N多节点到Dynamo Graph中才能实现,那就太麻烦了,如果处理的列表数据要更新几百个,那个Dynamo Graph就没法看了。
要解决也很简单:使用回代码。既可以使用CodeBlock,也可以使用PythonScript。
CodeBlock:
直接使用更新列表数据的语法List[index]=Value
因为Dynamo关联式语法的特征,会自动迭代列表为一一对应,从而实现更新所以索引为不同的数据。
PythonScript:
也是使用更新列表数据的语法List[index]=Value,但是因为PythonScript不支持关联式,需要遍历,核心代码如下:
DAT=IN[0]
IDX=IN[1]
VAL=IN[2]
for x,y in zip(IDX, VAL):
DAT[x]=y
return DAT
相对而言,还是CodeBlock的更加简单。