Skip to main content

Lists vs Collections

Learn when to use lists vs collections.

Lists and collections are similar data types that can contain an arbitrary number of elements of a given type. There are some differences:

  • A list offers fast random access to its elements;
  • A collection only computes its elements when that collection is consumed.
  • Lists are materialized immediately during creation.

Lists and collections can be build from items using the Build function of their respective libraries:

let planets = List.Build("Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"),
primeNumbers = Collection.Build(1, 2, 3, 5, 7, 9, 11)
in List.Count(planets) + Collection.Count(primeNumbers)

Surrounding items by brackets is the shorthand syntax to declare a list. There is no equivalent shorthand syntax to declare a collection.

let planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"],
primeNumbers = Collection.Build(1, 2, 3, 5, 7, 9, 11)
in List.Count(planets) + Collection.Count(primeNumbers)

Turning a collection into a list can be done with Collection.From (and vice-versa with List.From).

let planets = Collection.From(["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]),
primeNumbers = List.From(Collection.Build(1, 2, 3, 5, 7, 9, 11))
in Collection.Count(planets) + List.Count(primeNumbers)

Data readers like Csv.InferAndRead return a collection. It means the dataset is open and read only in the moment the collection is consumed. In the web service definition below, the CSV file is open and processed only during the execution of Collection.Count, and is done some one-item-at-a-time.

main(city: string) =
let airports = Csv.InferAndRead("https://raw-tutorial.s3.eu-west-1.amazonaws.com/airports.csv"), // types as a collection
canadaAirports = Collection.Filter(airports, a -> a.Country == "Canada") // a collection too
in Collection.Count(Collection.Filter(canadaAirports, a -> a.City == city))

Lists are computed and materialized in the moment of declaration. In the following code, airports, canadaAirports and the nested call to List.Filter are all materialized.

main(city: string) =
let airports = List.From(Csv.InferAndRead("https://raw-tutorial.s3.eu-west-1.amazonaws.com/airports.csv")), // now a list
canadaAirports = List.Filter(airports, a -> a.Country == "Canada") // a list too
in List.Count(List.Filter(canadaAirports, a -> a.City == city))

Since a list is entirely materialized, its possible to read items by index. Use List.Get to extract an item from a list. Here's an example that returns the planet name for a given index in the planets list.

main(index: int) =
let planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
in List.Get(planets, index)

(Note list index starts at zero. The planet at index 3 is Mars.)

info

If you want to try this example, you can deploy the following endpoint:

Tutorial 10 - Using lists
Learn different operations that can be performed on lists vs collections.

Usage:

/tutorial/10-lists?index=<int>

Note list index starts at zero. The planet at index 3 is Mars.

/tutorial/10-lists?index=3

The Collection library doesn't provide a Get function. Otherwise, all functions defined for collections also have equivalents in lists. For more information, consult the Snapi docs on lists vs collections.