Grasshopper Python 104

Lists

In the last post we discussed applying conditional operations to single values. But that is way too simple. We expect to process many different values when working with Grasshopper and the power of scripting increases when we deal with collections of data. The main collection type you should care about is The List.

Working With Lists

Lists can be created or processed within the scope of a Grasshopper Python scripting component. To access an input parameter as a list we must specify so in the context menu. This will allow us to iterate through all the elements of the list instead of performing the defined operations for each input by default, as happened in the examples in 103.

Now we can access the list as a whole to, for instance, measure how many elements are there in the list with the Count property.

a = "There are %d elements in the list" %(len(x))

# Here we are also using a variable placeholder.

Declaring Lists

In order to process a list we are going to need a bit more of flow control than just conditionals but before diving into loops let’s see how to declare and populate a list inside a Python component.

List declaration works like other variables but you need to supply values inside square brackets and separated by commas.

myList = [1,2,4,9,16,25]
# Lists are declared by providing several items within square brackets.

myEmptyList = []
# An empty list

myOtherList = ["perro", 1, 3.5, "dog"]
# A list containing different types

Operating with lists:

myList = []
# Declare an empty list

# Now fill it with the append() method.
# Enter the Fibonacci series

myList.append(1)
myList.append(1)
myList.append(2)
myList.append(3)
myList.append(5)
myList.append(8)
myList.append(15)

# This would be equivalent to
myList = [1,1,2,3,5,8,15]

# Print the number of items in the list
print "The list has %d items" % (len(myList))

# Retrieve a specific item in the list
print "Item at position 2 is %s" % (myList[2])

# You can retrieve also negative positions
print myList[-2]

# Create a trimmed version of the list with the : operator.
# :X will trim the remove the x items from the end.
myTrimmedList = myList[:3]
print myTrimmedList 

# X: will trim the remove the x items from the start.
myTrimmedList = myList[2:]
print myTrimmedList 

# We can use [:] to create a full copy of the list
myCopyList = myList[:]

print "Original and Copy Before Change"
print myList
print myCopyList

# Now change some value in myList
myList[0] = 100

print "Original and Copy after Change"
print myList
print myCopyList

#Finally let's make a copy a reverse the list

myReversedList = myList[:]
myReversedList.reverse()

print "List reversed"
print myReversedList

We interact with List mainly through methods and properties:

  • List.append(E) will add E to the list.
  • List.reverse() will invert the order of elements in the list.
  • List[i] will retrieve the element of the list with index i
  • Len(List) will return the number of items in the list;
  • Reference Types

    You have to be careful when dealing with lists as they behave quite different from inmutable variables like strings and doubles. Let’s seen an example:

    # Declare two variables, make the second equal to the first one
    myNumber1 = 8
    myNumber2 = myNumber1
    
    # Change the first one
    myNumber1 += 5
    
    # Print both variables
    print myNumber1
    print myNumber2

    The result here is something we would expect, the second variable gets the same as the first, then we alter the former but the later stays the same.

    Now let’s do something similar with a list of strings:

    #Declare a list
    myList = ["Dog","Cat","Bird","Elephant","Lion","Tiger","Parrot"]
    
    # Create the a new list and assign it the contet of myList
    myCopyList = myList
    
    print "Original and Copy Before Change"
    print myList
    print myCopyList
    
    # Now change some value in myList
    myList[0] = "Whale"
    
    print "Original and Copy after Change"
    print myList
    print myCopyList
    

    Look at the result:

    Weird right? Despite we only changed the first list, both outputs have been altered. That is because Lists, and Points, Surfaces, Meshes and everything else are Reference-Type variables, meaning that when we called myCopyList = myList; we where not copying the contents of one list into the other but actually linking both variables to the same data, so if we modify one we’ll do so for all of its references.

    That’s why, on the previous example, we created the copy of the list not using a plain “=” statement but we added the [:] operator.

    Challenge

    1. Write a component that checks if a list has an odd number of items and if so, returns the element at the middle.

    2. Write your own version of the List Item component.