简体   繁体   English

在Python中线性化列表的最短方法

[英]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. 我想从列表中使用线性增加的值创建一个列表,其中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 我的代码使用python字典

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? Numpy是一个选择,有些想法可以更好地以更加pythonic的方式完成这项任务吗? This function has to be called very frequently on big lists. 必须在大列表上频繁调用此函数。

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 :) 它现在只是一个班轮:)

Use collections.OrderedDict : 使用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]

A simpler solution without imports: 没有导入的更简单的解决方案:

input =[10,10,10,6,6,4,1,1,1,10,10]
d = {}
result = [d.setdefault(x, len(d)) for x in input]

I came up with this function using numpy which in my tests worked faster than yours when input list was very big like 2,000,000 elements. 我想出了这个函数使用numpy,在我的测试中,当输入列表非常像2,000,000个元素时,它比你的更快。

import numpy as np
def linearize(input):
    unique, inverse = np.unique(input, return_inverse=True)
    output = (len(unique)-1) - inverse
    return output

Also, this function only works if your input is in Descending order like your example. 此外,此功能仅在您的输入符合您的示例的降序时才有效 Let me know if it helps. 如果有帮助,请告诉我。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM