Why List Comprehension with groupby get weird results?

from itertools import groupby
dic = [{"name" : "A", "age": 15}, {"name" : "B", "age": 15},
 {"name" : "C", "age": 25}, {"name" : "D", "age": 25}]
print(len([(p, list(ps)) for _, ps in groupby(dic, key = lambda x: x["age"]) for p in ps])) #2
print(len([(p, ps) for _, ps in groupby(dic, key = lambda x: x["age"]) for p in ps])) #4

dic_g = groupby(dic, key = lambda x: x["age"])
print(len([(p, list(ps)) for _, ps in dic_g for p in ps])) #2
print(len([(p, ps) for _, ps in dic_g for p in ps])) # 0

dic_g = groupby(dic, key = lambda x: x["age"])
print(len([(p, ps) for _, ps in dic_g for p in ps])) #4
print(len([(p, list(ps)) for _, ps in dic_g for p in ps])) #0

dic_g = [(k, list(v)) for k, v in groupby(dic, key = lambda x: x["age"])]
print(len([(p, ps) for _, ps in dic_g for p in ps])) #4
print(len([(p, list(ps)) for _, ps in dic_g for p in ps])) #4

matrix = [(1, 2, 3), (4, 5, 6), (7, 8, 9)]
print(len([(e, list(r)) for r in matrix for e in r])) #9
print(len([(e, r) for r in matrix for e in r])) #9

I have use List Comprehension with groupby, but it will get weird results. It’s such behavior expected?

Yes, all of these look expected.

The central issue you are missing is that iterating through an object can be a destructive operation, and therefore iterating through it twice will not give you the same result. groupby, and all the “values” generators it yields are such object.

a = groupby([1,2,3])
for k, vs in a:
    print("First loop:", k, list(vs)) # runs three times

for k, vs in a:
    print("Second loop:", k, list(vs)) # doesn't run at all
2 Likes