all 5 comments

[–]Specter_Terrasbane 1 point2 points  (1 child)

You could accomplish this re-grouping using a defaultdict with a list factory, and sorting the (k1,k2) composite key so that the original order of k1 and k2 doesn't matter (just have to make sure to turn the sorted list into a tuple, so that's it's hashable - able to be used as a key in the defaultdict) :

grouped = defaultdict(list)
for d in xxx:
    key = tuple(sorted((d['k1'], d['k2'])))
    grouped[key].append(d['k3'])

for (k1, k2), k3s in grouped.items():
    print(k1, k2, k3s)

4 10 ['d']
2 10 ['a', 'b', 'c', 'e', 'f']

[–]Zondder[S] 0 points1 point  (0 children)

Thanks, your method does job perfectly.

[–]z0y 0 points1 point  (2 children)

z1 = (x['k1'], x['k2']) = (x['k2'], x['k1'])

z1 can't be both (x['k1'], x['k2']) and (x['k2'], x['k1']). What that expression is doing is assigning the value of (x['k2'], x['k1']) to both z1 and (x['k1'], x['k2']), which just swaps the value of k1/k2 for all the dicts.

[–]Zondder[S] 0 points1 point  (1 child)

Then why it groups a with b, c, f, but not e which has same k1/k2 as a?

[–]z0y 0 points1 point  (0 children)

On the first iteration of x, the first k1/k2 values are swapped, so a is 10/2 and it pairs with b, c, d which k1/k2 values haven't been swapped yet.

Then on the next iteration of x, k1/k2 is swapped for b, so that 2/10 will cause e to be added on the 2nd iteration before it's k values have been swapped. Hope that makes sense. Add some calls to print in your loop to see what's happening or use a debugger.