msampaio
msampaio

Reputation: 3433

Python sequence translation

I have a list of tuples like [(0, 34), (1, 77), (2, 6), (3, 60), (6, 2), (7, 5), (9, 13), (14, 2)]. I need to keep the tuples order and reenumerate second elements with integers from 0 to n - 1, where n is the list length. The result should be [(0, 4), (1, 6), (2, 2), (3, 5), (6, 0), (7, 1), (9, 3), (14, 0)].

I began writing a function that accepts integer sequences, but not integer pairs:

def translation(seq):
    return [sorted(set(seq)).index(x) for x in seq]

>>> translate([34, 77, 6, 60, 2, 5, 13, 2])
[4, 6, 2, 5, 0, 1, 3, 0]

`

Upvotes: 1

Views: 172

Answers (2)

Diego Allen
Diego Allen

Reputation: 4653

Try this. I modified the code you've given so it should be easy for you to understand.

def translation(seq):
    return [(x[0], sorted(seq, key=lambda t: t[1]).index(x)) for x in seq]

Sample usage:

>>> translation([(0, 34), (1, 77), (2, 6), (3, 60), (6, 2), (7, 5), (9, 13)])
[(0, 4), (1, 6), (2, 2), (3, 5), (6, 0), (7, 1), (9, 3)]

The key parameter in sorted lets you pass a function to do the ordering, the function lambda t: t[1] allows for the second element of each tuple to be used for ordering.

UPDATE

I updated my solution so translation([(1, 8), (4, 9), (12, 8)]) returns [(1, 0), (4, 1), (12, 0)].

def translation(seq):
    l = list(set(sorted([x[1] for x in seq])))
    return [(x[0], l.index(x[1])) for x in seq]

Upvotes: 1

georg
georg

Reputation: 215019

Maybe this:

xs = [(0, 34), (1, 77), (2, 6), (3, 60), (4, 2), (5, 5), (6, 13)] 
secs = sorted(set(x[1] for x in xs))
res = [(x[0], secs.index(x[1])) for x in xs]
print res # [(0, 4), (1, 6), (2, 2), (3, 5), (4, 0), (5, 1), (6, 3)]

or one single comprehension (but with quadratic performance):

res = [(x[0], sum(1 for y in xs if y[1] < x[1])) for x in xs]

Upvotes: 2

Related Questions