looks like DSCore doesn’t have List.Rank() method, how to get the maximum nested list level in Python
thanks christian, Python code is needed instead of DesignScript code
Can you post a simple, reproducible case?
import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
a=IN[0]
b=repr(a)
c=b.count("[")
OUT = c
following form of list data this way may be obsolete
cordially
christian.stan
import clr
clr.AddReference(‘DSCoreNodes’)
from DSCore import *
lst = [[1], [[2], [3]], [4]]
#OUT = List.Transpose(lst) # works OK
OUT = List.Rank(lst) # doesn’t work
You’ve defined a Dynamo list, not a Python one. They are called the same thing, but they aren’t. To make things more difficult for you, a List object from Dynamo will automatically be converted to a Python list which will outperform the Dynamo list as it’s native, just like moving a Python list between Dynamo nodes without converting it to a Dynamo list would slow things down there.
Once you make a valid Dynamo list, you can work with the list tools quite readily, but other Pythonic tools may not work.
To access the Rank property it’s actually easier to add the ProtoCore library to the CLR, import that library as an alias like PRT, and utilize the ‘Utils class and call the GetMaxRankForArray
method.
thanks JacobSmall for the insight, seems i have trouble to find GetMaxRankForArray
method, see below code FYI:
import clr
#clr.AddReference(‘DSCoreNodes’)
#from DSCore import *
clr.AddReference(‘ProtoCore’)
import ProtoCore as PRT
lst = [[1], [[2], [3]], [4]]
#OUT = List.Transpose(lst) # works OK
#OUT = List.Rank(lst) # doesn’t work
OUT = PRT.Utils.ArrayUtils.GetMaxRankForArray(lst)
Your list is still a Python list. Need to build a Dynamo one directly, which is not easily done. Everything you input will be converted to a Python list. Everything that makes a list will be converted to a Python list.
Basically, I can’t think of a situation where this is a good idea…
Why do you need it?
right, i’ll directly use List.Rank node as another input to Python node, thanks again.
This Python based method should do the trick in both CPython 3 and IronPython 2 engines:
def GetDepth(lst): #define the fuction
if not isinstance(lst, list): return 0 #if the input list isn't a list, return 0
depth = 1 #set the depth to 1
for obj in lst: #for each object in the list
if isinstance(obj, list): #is the object a list
d = 1 + GetDepth(obj) #set the variable d to one plus the result of GetDepth on the list to the list (calling the function within itself)
depth = max(depth, d) #set depth to the maximum of D and depth
return depth #return the depth
lst = [1, [2], [[3]], [[[4]]], [[[[5]]]]] #a list of lists and objects to test
OUT = GetDepth(lst), [GetDepth(l) for l in lst] #testing the definition and returning it to the Dynamo environment
and a simplification that’s hardter to annotate:
def depth(L): return isinstance(L, list) and max(map(depth, L))+1
lst = [1, [2],[[3]],[[[4]]],[[[[5]]]]]
OUT = depth(lst)
Another python solution, flattening nested lists or collections (for each level)
import sys
import clr
import System
from System.Collections.Generic import List
def is_collection(x):
return isinstance(x, list) or \
(hasattr(x, "GetType") and \
x.GetType().GetInterface("IEnumerable") is not None)
def get_max_rank(lst):
rank = 1
while any(is_collection(j) for j in lst):
rank += 1
lst = [list(i) for i in lst if is_collection(i)] # remove items are not list
lst = sum(lst, []) # flat the list
return rank
OUT = get_max_rank(IN[0])
thanks all, both works great! neat code of jacob.small recursive approach, and performance wise of c.poupin approach for very big list.