2017-03-27 22 views
1

有这种类似question,但不完全是我所问的。在列表中按长度排序查找具有相同值的子序列的索引

比方说,我有1和0的列表:

# 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的方式来做我以后的事情,就像回答前面的问题一样。这是我正在寻找的。

+0

你能告诉什么输出应该是什么样子的? –

+0

我只是这样做的:'[4,1,0,8,9]'。 – dabadaba

回答

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. 2map将产生一个迭代器而不是一个列表。你可以用来实现的结果,通过list(..)对 的结果。

+1

虽然这个问题被标记为Python 2,但可能值得一提的是'map'在Python 3中返回一个迭代器,而不是一个列表,所以你需要在'list()'调用中包装它。或者只是使用list comp而不是'map',这也有直接使用索引而不是调用函数来为每个项目建立索引的好处。 –

0

您可以使用groupbysorted功能与发电机功能来有效地做到这一点。

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,))] 
相关问题