Tseri
Tseri

Reputation: 31

How to map a unique id (counting from 0) to items in sublists

Let's say I have

a = [['a1', 'b1'], ['a1', 'b2'], ['a2', 'b1'], ['a2', 'b4']]

As a result I want

a = [[0, 2], [0, 3], [1, 2], [1, 4]]

Give an id to the first item of every sub-list (i.e a[:][0]) and then continue with the second item of every sub-list (i.e a[:][1])

I've tried:

>>> aa=[[] for cells in range(len(a))]
>>> for i in range(len(a)):
    for j in range(len(a[i])):
        aa[i].append(id(a[i][j]))

result:

>>> aa
[[34378168, 51409056], [34378168, 51507304], [34301464, 51409056], [34301464, 51467576]]

Which is "close" but I want the id to start from 0 and go on.

I know what id() returns and I don't need that.

Upvotes: 0

Views: 436

Answers (1)

Martijn Pieters
Martijn Pieters

Reputation: 1121844

Use collections.defaultdict() and itertools.count(); transpose the sublists with the zip() function first, transpose back again after assigning numbers:

from itertools import count
from collections import defaultdict

counts = defaultdict(lambda c=count(): next(c))

aa = zip(*((counts[cell] for cell in col) for col in zip(*a)))

The defaultdict() stores a new count() value each time a key has not yet been seen, producing a unique counter per string.

Demo:

>>> from itertools import count
>>> from collections import defaultdict
>>> a=[['a1', 'b1'], ['a1', 'b2'], ['a2', 'b1'], ['a2', 'b4']]
>>> counts = defaultdict(lambda c=count(): next(c))
>>> zip(*((counts[cell] for cell in col) for col in zip(*a)))
[(0, 2), (0, 3), (1, 2), (1, 4)]

Upvotes: 4

Related Questions