Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shortest way to linearize a list in Python

I want to make a list with linearly increasing values from a list with non-linearly increasing values in Python. For example

input =[10,10,10,6,6,4,1,1,1,10,10]

should be transformed to:

output=[0,0,0,1,1,2,3,3,3,0,0]

My code uses a python dictionary

def linearize(input):
    """
    Remap a input list containing values in non linear-indices list
    i.e.
    input = [10,10,10,6,6,3,1,1]
    output= [0,0,0,1,1,2,3,3] 
    """
    remap={}
    i=0
    output=[0]*len(input)
    for x in input:
        if x not in remap.keys():
            remap[x]=i
            i=i+1
    for i in range(0,len(input)):
        output[i]=remap[input[i]]
    return output

but I know this code can be more efficient. Some ideas to do this task better and in a more pythonic way, Numpy is an option? This function has to be called very frequently on big lists.

like image 674
linello Avatar asked Dec 18 '25 13:12

linello


2 Answers

As per your comment in the question, you are looking for something like this

data = [8,8,6,6,3,8]
from itertools import count
from collections import defaultdict
counter = defaultdict(lambda x=count(): next(x))
print([counter[item] for item in data])
# [0, 0, 1, 1, 2, 0]

Thanks to poke,

list(map(lambda i, c=defaultdict(lambda c=count(): next(c)): c[i], data))

Its just a one liner now :)

like image 74
thefourtheye Avatar answered Dec 20 '25 10:12

thefourtheye


Use collections.OrderedDict:

In [802]: from collections import OrderedDict
     ...: odk=OrderedDict.fromkeys(l).keys()
     ...: odk={k:i for i, k in enumerate(odk)}
     ...: [odk[i] for i in l]
Out[802]: [0, 0, 0, 1, 1, 2, 3, 3, 3]
like image 32
zhangxaochen Avatar answered Dec 20 '25 10:12

zhangxaochen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!