2020-06-11
|~5 min read
|994 words
Python has a very concise syntax for creating new lists called List Comprehension.
List comprehension is a way to define a new list based on an old one.
In this post I’ll:
The syntax for a list defined with list comprehension has four pieces (some of which are optional):
new_list
el
for el in old_list
if el != None
This looks like:
new_list = [el for el in old_list if el != None ]
NB: The expression must reference the variable used to to find elements in the old list. So while new_list = [el for el in old_list]
is valid, new_list = [number for el in old_list]
will throw an error. The same is true for the filter.
First up, creating a list of odd numbers between 1 and 10 in Python.
We begin by constructing our base list:
>>> numbers = []
>>> for number in range(1,11):
... numbers.append(number)
...
>>> numbers
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Now we want to filter out odd numbers, we could use the same for loop strategy:
>>> odd_numbers = []
>>> for number in numbers:
... if number % 2 != 0:
... odd_numbers.append(number)
...
>>> odd_numbers
[1, 3, 5, 7, 9]
But list comprehension allows a more concise syntax:
>>> odd_numbers = [number for number in numbers if number % 2 != 0]
>>> odd_numbers
[1, 3, 5, 7, 9]
But what if we didn’t want to filter. Instead we wanted to transform - doubling each number in the list for example:
>>> doubles = [number * 2 for number in numbers]
>>> doubles
[2, 4, 6, 8, 10, 12, 14, 16, 18, 20]
And now putting that together - filtering out the evens, and then tripling the remaining values:
>>> triple_odds = [number * 3 for number in numbers if number % 2 != 0]
>>> triple_odds
[3, 9, 15, 21, 27]
Now that we understand list comprehension, we can see that we could have created our first list more concisely too:
>>> numbers = [number for number in range(1,11)]
>>> numbers
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Before moving on, let’s look at those side-by-side to see how list comprehension mirrors the syntax of the for-loop / if-statement:
>>> numbers = [number for number in range(1,11)]
>>> numbers
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> triple_odd = [number * 3 for number in numbers if number % 2 != 0]
>>> triple_odd
[3, 9, 15, 21, 27]
>>> triple_odd = [] # reset the variable
>>> for number in numbers:
... if number % 2 != 0:
... triple_odd.append(number * 3)
...
>>> triple_odd
[3, 9, 15, 21, 27]
The expressions are almost identical, though the list comprehension is in one line:
number * 3
is the expression in the list comprehension in the first position. It is the last thing to occur in our for/if statement.if number % 2 != 0
is the filter in the list comprehension (last position), and the middle place in the for/if statement.for number in numbers
is the loop over the old list and is in the second position of our list comprehension and kicks off the for/if statement.Now that we’ve seen how it’s done in Python, let’s take a look at how you might achieve similar results in Javascript.
One of the interesting things about learning a new language is to see how it compares to others.
Here, I’ll look at how I might achieve the same results of list comprehension with Javascript.
Javascript used to have array comprehension, but it’s been deprecated which means we’ll need a different strategy here.
We get a hint for how to approach this from the documentation on array comprehensions:
Comprehensions can often be used in place of calls to map() and filter() , or as a way of combining the two.
Since array comprehension was about combining maps and filters, we’ll likely be able to achieve the same results by combining those.
Let’s take a look at the same example above of creating a numbers array, then finding an odd numbers and a triple odd numbers list.
First, let’s be fancy and use Array.from()
and it’s second argument, which is a map to generate our range of numbers 1-10.1
let numbers = Array.from(new Array(10), (_, i) => i + 1)
console.log(numbers) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Now, we can create a filter to get our odd numbers:
let oddNumbers = numbers.filter((num) => num % 2 !== 0)
console.log(oddNumbers) // [1, 3, 5, 7, 9]
And for our triple odd numbers:
let tripleOddNumbers = numbers
.filter((num) => num % 2 !== 0)
.map((odd) => odd * 3)
console.log(tripleOddNumbers) // [3, 9, 15, 21, 27]
In our case, the order actually does not matter, however filtering before mapping is slightly more efficient as we reduce the number of elements we’ll need to map over:
let tripleOddNumbers = numbers
.map((number) => number * 3)
.filter((number) => number % 2 !== 0)
console.log(tripleOddNumbers) // [3, 9, 15, 21, 27]
Hi there and thanks for reading! My name's Stephen. I live in Chicago with my wife, Kate, and dog, Finn. Want more? See about and get in touch!