查找按长度排序的列表中相同值的子序列的索引

时间:2017-03-27 10:34:58

标签: python python-2.7 list group-by

有类似的question,但不是我要问的。

我们说我有一个零和一个零的列表:

# i.e. [1, 0, 0, 0, 1, 1, 1, 1, 0, 1]
sample = np.random.randint(0, 2, (10,)).tolist()

我试图找到相同值的子序列的索引,按其长度排序。所以在这里,我们将有以下子列表:

[1, 1, 1, 1]
[0, 0, 0]
[1]
[0]
[1]

所以他们的指数是[4, 1, 0, 8, 9]

我可以得到排序后的子序列:

sorted([list(l) for n, l in itertools.groupby(sample)], key=lambda l: -len(l))

然而,如果我重复后续步骤,我将无法立即找到索引(我将不得不使用另一个循环)。

我觉得有一种更直接和Pythonic的方式来做我以后的事情,就像前面问题的答案所表明的那样。这就是我正在寻找的。

2 个答案:

答案 0 :(得分:1)

您可以先使用enumerate(..)创建索引和值的元组。接下来是groupby,但是在元组的第二个元素上,最后将它们映射回第二个索引。像:

map(lambda x:x[0][0], # obtain the index of the first element
    sorted([list(l) for _,l in itertools.groupby(enumerate(sample), # create tuples with their indices
                                                 key=lambda x:x[1])], # group in value, not on index
           key=lambda l: -len(l)))

在控制台中运行(压缩命令)时,它会产生:

>>> map(lambda x:x[0][0],sorted([list(l) for _,l in itertools.groupby(enumerate(sample),key=lambda x:x[1])],key=lambda l: -len(l)))
[4, 1, 0, 8, 9]
  

<强> N.B。 1 :排序时,您可以使用lambda l: -len(l)(和key),而不是将reverse=True用作key = len。   声明的,如:

map(lambda x:x[0][0],
    sorted([list(l) for _,l in itertools.groupby(enumerate(sample),
                                                 key=lambda x:x[1])],
           key=len, reverse=True))
     

<强> N.B。 2 :在 map中会生成迭代器,而不是列表。您可以通过调用list(..) 实现结果   结果。

答案 1 :(得分:0)

您可以使用带有生成器功能的groupby sorted函数来有效地执行此操作。

from itertools import groupby
from operator import itemgetter

data = [1, 0, 0, 0, 1, 1, 1, 1, 0, 1]

def gen(items):
    for _, elements in groupby(enumerate(items)):
        indexes, values = zip(*elements)
        yield indexes[0], values        

result = sorted(list(gen(data)), key=lambda x: len(x[1]), reverse=True)

打印结果产量:

[(4, (1, 1, 1, 1)), (1, (0, 0, 0)), (0, (1,)), (8, (0,)), (9, (1,))]