For sure list-comprehensions are a beautiful Python feature, but I've realised that I've been overusing them lately, applying a list comprehension to another list-comprehension, which makes the code not particularly clear. This has led me to compare it with the common approach followed in other languages: chaining methods on collections (JavaScript array extras or lodash, linq, pydash in python itself, Kotlin collections methods...). Let's compare some examples:
Using nested list comprehensions like this in Python seems pretty elegant to me:
cities = [ city.upper()
for country in countries if country.name.startswith("c")
for city in country.cities if city.name.startswith("c")
]
We can write an equivalent in "chaining style" in JavaScript like this:
let cities = countries.filter(country => country.startsWith("c"))
.flatmap(country => country.cities)
.filter(city => city.startsWith("c")
.map(city => city.toUpper());
In this case I think I prefer the list-comprehensions option.
Nested list-comprehensions are also very nice if I want to combine values from the main and the nested collection. For example here, where I want a listing of country-city:
country_and_cities = [ [country.name, city.name]
for country in countries
for city in country.cities
]
That I would write in "chaining style" in JavaScript like this
let countryAndCities = countries.flatMap(country => country.cities.map(city => [country.name, city.name]));
Let's go now with those cases where I think list-comprehensions make code not so pleasant to read.
For example for parsing some lines read from a CSV into a list of objects we would write:
@dataclass
class Person:
name: str
age: int
countries = [Person(items[0], int(items[2])
for items in [
line.split(",")
for line in lines if not line.startswith("--")
]
]
We would write it in "chaining style" in javascript like this:
lines.filter(line => !line.startsWith("--")
.map(line => {
let [name, age] = line.split(",");
return new Person(name, int(population));
});
And for dumping a list of objects to a CSV string we have this Python code with list-comprehensions:
users = [Person("Francois", 55), Person("Iyan", 45)]
"\n".join([user_line for user_line in
[";".join(user.name, str(user.age))
for user in users]
])
That I think looks better in "chaining style" with javascript like this (or using pydash in python for example)
users.map(user => [user.name, user.age].join(";"))
.join("\n");
No comments:
Post a Comment