Dynamo List sorting question


#1

I have two questions:

 

How would I sort a list of XYZs by Z value, and then break into a list of lists sorted by X value?

 

On a related note, why would the XYZ X node on the far right give varying values for the Z, especially when they were accurate, and verified by typing the height parameter value in Revit?

 


#2

Hi guys,


I wanted to add another solution to the discussion as I have worked on a similar problem of sorting lists this week.
I ended up using one of Python's abilities to handle lists which is called groupby() because I did not want my head to hurt thinking about how to go about this in Dynamo... ;-)


Here's how:



  1. Sort list by X values using the method Steve explains above

  2. Sort list by Z values
    (Notice that within each group of equal Z values, the X values retain their order from the previous sort operation)

  3. Create a list of lists with XYZ values (sublist 0) and just Z values (sublist 1)

  4. Group that list of lists by the Z values (using a custom node with some Python code inside)

  5. Extract only the list of lists of XYZs by combining two map nodes


You will need the package Group List of Lists By Key for this to work.


(For what it's worth, I also uploaded another package called Sort List Of Lists this week which was related to that project but isn't needed here. But it might be worth checking out, too.)


here the other day. I am now using a custom node called Almost Zero (also in the package manager) as tolerance for XYZ-based calculations and rounding.


#3

It is crazy. My head hurts, and I like it.


#4

Guys, thanks for the lesson. a perfect way to learn Map, Compose, etc…in fact how to use a node as a function. Excellent! crazy but excellent!


#5

Curry, huh? How spicy? Hehe. I'll chew on this for a bit. It does appear to solve the problem. Thanks so much. I hope you still have most fo your hair, mine started falling out yesterday - and I suspect it's due to this challenge. ;)


#6

Here's my (rather complicated) solution:



This requires two packages from the Dynamo Package Manager: remove duplicates and Curry.


The idea is that you want a sub-list for each unique Z component of your XYZs. That means the goals are to find all unique Z values, then for each value filter the list so that only XYZs with that Z value remain.



  1. Use remove duplicates to generate a list of unique Z components from the XYZs.

  2. Build up a filter predicate by

    1. Create a function that accepts a number and returns true if it equals a certain unique Z component. Since Map expects a 1-argument function, and Equal is a 2-argument function, we need to use Curry to turn Equal into a 1-argument function that returns a function that will accept the second argument.

    2. Create a new function that first extracts the Z component from an XYZ and then passes it to the previous function.



  3. Now you have a filter predicate for each unique Z component. You can Map over these, passing each into Filter, which will produce the sub-lists.

  4. For each sub-list, sort by the X component using Sort by Key.



Obviously this workflow is a little crazy, so expect a node for this kind of thing in the future.


#7

Fantastic! What I’d then like to do is identify all Z values that are the same and break the lists… This will let me perform my end goal of numbering the elements (windows in this case) by column and by row. So, if there’s a series of Z values that are ‘3’ and another bunch ‘13’ etc, I can a break at the unique values.





I really appreciate the help.


#8

In the workflow, I use the XYZ Z node as a function (note the missing input) that I pass to Sort by Key, which in turn applies it to every item in the list. The list is then sorted based on the output of XYZ Z.



Could you elaborate a little more on how you want to break this into sub-lists sorted by X axis?



The slight discrepancy between the numbers is due to floating-point inaccuracy in all computers, and can be ignored. The difference between the numbers is so minuscule that it doesn't matter.


#9

Interesting solutions here – thanks everyone for posting, it’s been a huge help.

Let’s say these XYZs are extracted from a list of Revit family instances. This method sorts their XYZ locations into groups, but how might I group the Revit instances into these groups (instead of only grouping their XYZs)?


#10

I think you are looking for something like Andreas’s Group list of lists by key package, or I also just submitted something similar to the package manager. Look for Group Items By Key List.

Capture


#11

Not sure if my package actually works in 0.7 - haven’t tested it yet. You better go with Colin’s package if you’re running 0.7 …


#12

FYI, here’s the info on updating Python definitions for 0.7.0. For non-Revity Python definitions, it’s mostly a case of changing the input statements.

https://github.com/DynamoDS/Dynamo/wiki/Python-0.6.3-to-0.7.x-Migration