Python 从列表中创建等值索引的子列表

Python 从列表中创建等值索引的子列表,python,python-3.x,list,Python,Python 3.x,List,我试图将一个整数列表拆分为相等整数索引的子列表。假设我有一张清单: original_list = [1,2,1,4,4,4,3,4,4,1,4,3,3] 所需的输出将是: indexes : [[0,2,9], [1], [6,11,12], [3,4,5,7,8,10]] # corresponds to sublists: [[1,1,1] [2], [3,3,3], [4,4,4,4,4,4]] 虽然我不知道如何做到这一点,因为大多数解决方案都要求您首先对原始列表进行排序,但在我的例

我试图将一个整数列表拆分为相等整数索引的子列表。假设我有一张清单:

original_list = [1,2,1,4,4,4,3,4,4,1,4,3,3]
所需的输出将是:

indexes : [[0,2,9], [1], [6,11,12], [3,4,5,7,8,10]]
# corresponds to sublists: [[1,1,1] [2], [3,3,3], [4,4,4,4,4,4]]
虽然我不知道如何做到这一点,因为大多数解决方案都要求您首先对原始列表进行排序,但在我的例子中,这会弄乱索引。由于这个原因,Itertools或np.array对我没有帮助,因为它们只对顺序相等的元素进行分组


有人知道这个问题的解决方案吗?我很想听

您可以使用
枚举

original_list = [1,2,1,4,4,4,3,4,4,1,4,3,3]
groups = {a:[i for i, c in enumerate(original_list) if c == a] for a in set(original_list)}
输出:

{1: [0, 2, 9], 2: [1], 3: [6, 11, 12], 4: [3, 4, 5, 7, 8, 10]}

这可以通过列表理解来实现

>>> x = [1,2,1,4,4,4,3,4,4,1,4,3,3]
>>> [[i for i in range(len(x)) if x[i]==y] for y in sorted(set(x))]
[[0, 2, 9], [1], [6, 11, 12], [3, 4, 5, 7, 8, 10]]
使用和,可以使用

from collections import defaultdict

dd = defaultdict(list)
for index, value in enumerate(original_list):
    dd[value].append(index)

print(dd)
# defaultdict(<class 'list'>, {1: [0, 2, 9], 2: [1], 4: [3, 4, 5, 7, 8, 10], 3: [6, 11, 12]})
从集合导入defaultdict
dd=默认DICT(列表)
对于索引,枚举中的值(原始列表):
dd[值]。追加(索引)
印刷品(dd)
#defaultdict(,{1:[0,2,9],2:[1],4:[3,4,5,7,8,10],3:[6,11,12]})
您可以将其用于一次性解决方案。然后使用
排序
,如果您需要,就像在您想要的结果中一样,按值对索引进行排序

original_list = [1,2,1,4,4,4,3,4,4,1,4,3,3]

from collections import defaultdict
from operator import itemgetter

dd = defaultdict(list)

for idx, value in enumerate(original_list):
    dd[value].append(idx)

keys, values = zip(*sorted(dd.items(), key=itemgetter(0)))

print(keys, values, sep='\n')

(1, 2, 3, 4)
([0, 2, 9], [1], [6, 11, 12], [3, 4, 5, 7, 8, 10])
为了进行比较,
dd
的值在Python 3.6+中按插入顺序排列(正式在3.7+中,作为3.6中的CPython实现细节):


下面是我将如何使用numpy,使用我在注释中链接的argsort函数

original = [1,2,1,4,4,4,3,4,4,1,4,3,3]
indexes = []
s = set()

for n in np.argsort(original):
    if original[n] in s:
        indexes[-1].append(n)
    else:
        indexes.append([n])
        s.add(original[n])

print(indexes)

仅供参考,numpy中有一个合适的排序函数:这里不要挑剔,但它的时间复杂度非常糟糕。@ninesalt lol,你就是这么做的。然而,在这种情况下,理解就足够了,因为它是一次性的。如果必须反复执行类似操作,则应使用不同的数据结构。过早优化是不必要的。此外,对于小列表(甚至多达几千个元素),此操作的实际执行时间非常短,因此此解决方案可以正常工作。它是正确的,紧凑的,工作正常。我也很喜欢Ajax1234的答案。但是,嘿,数组索引是固定时间的,嗯?我明白你的意思,但是在你需要改进它之前,你不应该用“坏”的方式,即使这是一次性的。OP并没有提到复杂性,所以在本例中这显然无关紧要,这只是一个旁注。还有,看看我的答案。但问题是,这不是“坏方法”。事实上,从一个正确的解决方案开始,逐步改进优化解决方案,同时保持正确性,是从规范中导出程序的一种非常重要的方法。这种方法得到了唐纳德·克努斯、理查德·伯德和其他一些人的支持。看看如何巧妙地利用这个场景来记录你所看到的东西。Python的sorted可以在不牺牲性能的情况下替换为numpy的,而且它会返回一个新列表,这样第一个列表就不会被修改。干得好。@xerosmith您实际上无法交换Pythons排序函数,因为它执行其他操作。它返回元素的索引,而不是元素本身。此外,它不会修改原始列表。
original = [1,2,1,4,4,4,3,4,4,1,4,3,3]
indexes = []
s = set()

for n in np.argsort(original):
    if original[n] in s:
        indexes[-1].append(n)
    else:
        indexes.append([n])
        s.add(original[n])

print(indexes)