I’m trying to merge 4 separate lists into one list. I want to replace the nulls by matching the index order. For example, these two lists so the nulls at 465-472 get replaced with the list below. Replace Item at Index won’t help. Thanks!!
Edit: As noted lower in this thread, Function Passing (A concept this node uses - notice the lack of a wire going into the Object.IsNull node, is slower at scale than other options. Suggestion would be to use @Nick_Boyts & @jacob.small’s option.
Here is another option Please do test on real data though as mine is simply mock-data.
- Requires both lists to be identical in length
- Requires all nulls in first list (That get replaced) to have a corresponding correct Element in second list
The reason List.ReplaceItemAtIndex fails is that a
null is special case and throws all kinds of oddness into the mix. You should be able to use this node for any non-null case in a similar way.
You can also accomplish this with a simple If statement and a null check.
All of these work, but when looking at things from a speed standpoint: Nick’s solution of
listA==null ? listB: listA; is likely best.
I put all three methods into a graph with a variable list size to play with. When working with small lists the difference is basically nothing. At 100 elements you could feel the slow down. But at scale (40,004 items) with a nested list of lists things had a clear difference.
In all cases the ReplaceByCondition node is slowest (function passing is slow in Dynamo, and this node takes a function as an input so that’s expected). In my test of 40,004 elements It took 163.231 seconds to finish.
The solution of a List.Create, a List.Transpose, a List.Clean and a List.Flatten was quick, coming in at 1.866 seconds. Note that this requires an extra List.Transpose node right after the first one to deal with nested list conditions. The exact structure of the transpose nodes and graph will vary based on the overall list structure, meaning you’ll have to know what format things will be in before they get there, which is not always a certainty.
The solution of some design script is not only the fastest at 0.707 seconds, but also works with both nested and un-nested list structures due to design script’s associative lacing.
Further testing (excluding the replace by condition due to the speed issue) had varying results, but the design script was always fastest.
Providing my toy for anyone else who’d like to study the options.
Relacing Nulls.dyn (31.6 KB)
On occasion, if he had 4 lists as mentioned in his problem with nested ifs in design script, I see how to do it
(I tried in python to progress, with the zip method, is my loop depth wrong?)
# Charger les bibliothèques DesignScript et Standard Python import sys import clr clr.AddReference('ProtoGeometry') from Autodesk.DesignScript.Geometry import * # Les entrées effectuées dans ce noeud sont stockées sous forme de liste dans les variables IN. list_1=IN list_2=IN list_3=IN list_4=IN list_compile= list_compile2= #votre code au-dessous de cette ligne for i in list_1: if not (i is None): list_compile.append(i) for j in list_2: if not (j is None): list_compile.append(j) for k in list_3: if not (k is None): list_compile.append(k) for l in list_3: if not (l is None): list_compile.append(l) #try with zip list for m,n,o,p in zip(list_1,list_2,list_3,list_4): if not (m is None): list_compile2.append(m) if not (n is None): list_compile2.append(n) if not (o is None): list_compile2.append(o) else: list_compile2.append(p) # Affectez la sortie à la variable OUT. OUT = list_compile,list_compile2
The only difference is whether the initial lists are combined or not. You can still use design script on any number of sublists, as long as you know the order of priority.
It’s the same thing with python.
Thanks for writing with similar structure
Hello, I tried another method
# Charger les bibliothèques DesignScript et Standard Python import sys import clr clr.AddReference('ProtoGeometry') from Autodesk.DesignScript.Geometry import * # Les entrées effectuées dans ce noeud sont stockées sous forme de liste dans les variables IN. list_compile= #votre code au-dessous de cette ligne for i in range(len(IN)): a=[IN[i],IN[i],IN[i],IN[i]] for x in a: if x!=None: b=x list_compile.append(b) # Affectez la sortie à la variable OUT. OUT = list_compile
Just a few comments on your code…
This may just be personal preference, but in my mind this is just a more complicated way of saying
for i,j,k,l in zip(IN,IN,IN,IN): a=[i,j,k,l]
This is also a bit redundant since you can just append x.
The main issue here is that your code is dependent on indices only containing one value per sublist and doesn’t take into account indices containing no value in any sublist. And maybe that’s fine for this particular example, but it would cause problems for general use.
Just some things to consider.
Thanks for sharing knowledge