Hello,
I’m trying to sort elements in a “slalom” sequence.
A list contains several ranges.
These ranges contain several subranges, each containing a different number of elements.
These should now be sorted according to their position, since they can be numbered in a loop.
For example, I first sorted by the Y coordinate, and then by the X coordinate within this sorting sequence.
That’s all working so far.
But to get a descending order in certain ranges, for example, with an odd index, I have to do it with List.Reverse.
However, List.Reverse simultaneously creates a new list instead of just sorting the relevant elements in the subrange of the list/sublist in descending order.
But how do I combine the ascending and descending sorted elements back into one list?
However, the list structure must be maintained with regard to the different areas with different numbers of objects, precisely because each of them is considered separately.
Thank you very much in advance.
Hi, and welcome !
here is an solution with python
import clr
import sys
import System
#
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
import Autodesk.DesignScript.Geometry as DS
#import Revit API
clr.AddReference('RevitAPI')
import Autodesk
from Autodesk.Revit.DB import *
import Autodesk.Revit.DB as DB
clr.AddReference('RevitNodes')
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
#import transactionManager and DocumentManager (RevitServices is specific to Dynamo)
clr.AddReference('RevitServices')
import RevitServices
from RevitServices.Persistence import DocumentManager
from RevitServices.Transactions import TransactionManager
doc = DocumentManager.Instance.CurrentDBDocument
import itertools
toList = lambda x : x if hasattr(x, "__iter__") and not isinstance(x, (str, System.String)) else [x]
#Preparing input from dynamo to revit
lstelems = toList(UnwrapElement(IN[0]))
lstelems = sorted(lstelems, key = lambda x : (x.Location.Point.X, x.Location.Point.Y))
out = []
for idx, (key_, group) in enumerate(itertools.groupby(lstelems, key = lambda x : round(x.Location.Point.X, 2))):
if idx % 2 == 0: # check if the index is an even number
out.extend(list(group))
else:
out.extend(list(group)[::-1]) # if not reveerse the list group
OUT = out
Hello C.,
Thank you for your support.
I tried that, but unfortunately I get an error message:
SystemError: returned a resiult with an error set [‘File “<string”, line 16, in \n’]
What could be the problem?
Unfortunately, I don’t have any experience with Python…
In any case, thank you very much for your effort.
Restart Revit and try to flatten your list before the python node.
Elements must be sorted by group ?
If you have the sorting and grouping worked out then you’re 90% there. You just have to use a conditional to alternate directions between groups.
1 Like
You could also consider reversing every alternate list
lst1 = List.SortByKey(lst[0],lst[0].X)["sortedList"];
lst2 = List.GroupByKey(lst1,lst1.X)["groups"];
lst3 = List.SortByKey(lst2<1>,lst2.Y<1>)["sortedList"];
lst4 = List.Transpose(List.Chop(lst3,2));
lst5 = List.Reverse(lst4[1]<1>);
lst6 = List.Flatten(List.Transpose([lst4[0],lst5]),-1);
PolyCurve.ByPoints(lst6,false);
4 Likes
Hello,
Thank you very much for your support.
@Cyril:
Unfortunately, I haven’t been able to get your Python script to work yet.
It seems it can’t find certain libraries; I’m currently trying to clarify this with IT regarding the installation.
@Nick:
I was able to implement the principle of your Dynamo script, and yes, it worked and produced the desired result.
This arrangement of the IF statement was the key to staying within the list with List.Reverse.
Finally, because I was already at my wit’s end… 
@Vikram:
I’ll definitely take a closer look at your suggestion…
It looks very interesting, although I’m not entirely sure about the list principle yet, so I’ll have to work it out a bit more.
But I have a solution for my problem, really great…
Screenshot_ready.pdf (621.7 KB)
2 Likes