Weave lists of pts together

I am new to python (sort of), anyway I am not sure why this is not working. Should be simple to weave two lists together with a boolean pattern of true false.

I don’t really understand how to flatten the two lists after using python’s built in ‘zip’ function.

import rhinoscriptsyntax as rs

list1 = []
list2 = []
list3 = []


for x in range (0,20,2):
    y = 0
    z = 0
    ptlist1 = rs.AddPoint(x,y,z)
    list1.append(ptlist1)
    
    for x2 in range (0,20,3):
        y = 0
        z = 0
        ptlist2 = rs.AddPoint(x2,y,z)
        ptlist2move = rs.MoveObjects(ptlist2, (0,5,0))
#        rs.DeleteObjects(ptlist2)
        list2.append(ptlist2move)
        
def weaveLists():
    zip(list1, list2)
    flattenList = [item for sublist in zip(list1, list2) for item in sublist] #this line confuses me
    list3.append(flattenList)
    return rs.AddPolyline(list3)
    
# attempting to weave lists together with a boolean pattern like the 'weave' pattern in 
# grasshopper.

It seems to work here in my example below (I didn’t test your script yet).
The line you don’t understand is a list comprehension, it’s just a shorthand for some longer code.

result=[item for sublist in mainlist for item in sublist]

#is the same as

result=[]
for sublist in mainlist:
    for item in sublist:
        result.append(item)

I used the following example to test the method:

list0=["A","B","C","D","E"]
list1=["AA","BB","CC","DD","EE"]
list2=["AAA","BBB","CCC","DDD","EEE"]

zipped=zip(list0,list1,list2)
result0=[item for sublist in zipped for item in sublist]

result1=[]
for sublist in zipped:
    for item in sublist:
        result1.append(item)
print result0
print result1

In looking at your example, I think you also want to change this line:

list3.append(flattenList)
to this
list3.extend(flattenList)

  • if you are trying to create a flat list for rs.AddPolyline(). Append will append the entire list3 to the existing list as one item and you will no longer have a flat list. Extend will append each item of the new list to the end of the existing one in order (i.e. extending the list).

HTH, --Mitch

Thank you for your comprehensive response Mitch,

I see in your example that both ‘result1’ and ‘result0’ yield the same result with the shorthand and the longer code. It is still somewhat confusing, but I’ll analyze further. Interesting use of ‘extend’ as I am still learning lists in python.

Nevertheless, I still cannot manage to get the polyline between the two sets of points. You said that it worked for you?

Than you again very much,

Erik

No, there are a bunch of other things wrong with the script, I will try to cover them one by one.

  1. A common mistake is to use pt=rs.AddPoint() when creating 3D points. This actually adds a point object to the document, which you may or may not want, and it returns that point object’s GUID, not the point coordinates. Use something like rs.coerce3dpoint([x,y,z]) to create a rhino/python “Point3d” object, which has the characteristics of a point, but does not get added to the document.

  2. ptlist2move = rs.MoveObjects(ptlist2, (0,5,0))
    has three things wrong with it - first, adding the point object to the document as described above and expecting it to return coordinates, second, no need to create a point and then move it - just create it directly in place, and third, MoveObjects() will return a list and not a single item.

  3. your def weaveLists() is created but never called, and it wouldn’t work anyway because list3 is never defined - and not actually needed. In this simple case, it’s not really necessary to create a separate weavelists definition, so I just removed it and included it the whole script below.

  4. Note also that your list lengths are not the same, the second is shorter. When you zip them, the longer list will be truncated to the same length as the shorter one. So not all points get used (would be the same in GH).

import rhinoscriptsyntax as rs
list1 = []
list2 = []
    
y=0
z=0
for x in range (0,20,2):
    #make a 3d point object from your coordinates
    #(does not add a point object to document)
    pt1=rs.coerce3dpoint([x,y,z])
    rs.AddPoint(pt1) #optional if you really want the point to be added
    list1.append(pt1)
    
#same as above - except create the points directly at y=5
y=5
for x2 in range (0,20,3):
    pt2=rs.coerce3dpoint([x2,y,z])
    rs.AddPoint(pt2) #optional
    list2.append(pt2)
    
flattened = [item for sublist in zip(list1,list2) for item in sublist]
rs.AddPolyline(flattened)

HTH, --Mitch

Hey Mitch,

I appreciate your detailed response. I have been rather confused on how lists work in Python coming from Grasshopper. This has helped me out a lot!

The code: [item for sublist in zip(list1,list2) for item in sublist] is pretty handy.

Thanks so much,
Erik

Yeah, Grasshopper does a whole bunch of stuff behind the scenes that you don’t realize to automate things and make components “intelligent”, writing code in Python - or any other language for that matter - will be more “manual”.

–Mitch

Yes, definitely. I certainly didn’t invent that one, I just found it in a post on StackOverflow… (Google is your friend)

BTW, if you do actually want to work with a function definition, you can create a “list weaver” something like this and then call it as needed:

def ListWeaver(nested_list):
    zipped_list=zip(*nested_list)
    return [item for sublist in zipped_list for item in sublist]
    
list0=["A","B","C","D","E"]
list1=["AA","BB","CC","DD","EE"]
list2=["AAA","BBB","CCC","DDD","EEE"]
    
print ListWeaver([list0,list1,list2])

This will weave any number of lists together…

–Mitch

1 Like