【问题标题】:Compare all lists within list of lists based on condition and group them together by their difference根据条件比较列表列表中的所有列表,并根据它们的差异将它们组合在一起
【发布时间】:2019-02-28 08:27:57
【问题描述】:

我有以下列表:

a = [[1,2,3,4,5], [4,5,6,7,8], [1,2,3,4], [4,5,6,7,8,9], [2,3,4,5,6,7,8], [6,7,8,9], [5,6,7,8,9], [2,3,4,5,6], [3,4,5,6], [11,12,13,14,15], [13,14,15]]

用索引表示它们以便于理解:

0 [1, 2, 3, 4, 5]
1 [4, 5, 6, 7, 8]
2 [1, 2, 3, 4]
3 [4, 5, 6, 7, 8, 9]
4 [2, 3, 4, 5, 6, 7, 8]
5 [6, 7, 8, 9]
6 [5, 6, 7, 8, 9]
7 [2, 3, 4, 5, 6]
8 [3, 4, 5, 6]
9 [11, 12, 13, 14, 15]
10 [13, 14, 15]

我期待的输出将是一个元组列表,如下所示:

output = [(0,2,1), (3,1,1), (4,7,2), (4,1,2), (6,5,1), (3,5,2), (3,6,1), (7,8,1), (9,10,2)]

For example to explain first item of output i.e, (0,2,1):

0 ---> index of list under comparison with highest length 
2 ---> index of list under comparison with lowest length
1 ---> difference in length of the two lists 0 & 2

现在,问题来了:

我的列表有相似的项目,在列表的开始或结束时长度相差一个和两个(或三个)。

我想对列表的索引及其作为元组的区别进行排序、分组、识别。

我检查了多个 stackoverflow 问题,但找不到类似的问题。

我是 python 新手,从以下代码开始,然后卡住了:

a = sorted(a, key = len)

incr = [list(g) for k, g in groupby(a, key=len)]

decr = list(reversed(incr))

ndecr = [i for j in decr for i in j]

for i in range(len(ndecr)-1):
    if len(ndecr[i]) - len(ndecr[i+1]) == 1:
        print(ndecr[i])

for i in range(len(ndecr)-2):
    if len(ndecr[i]) - len(ndecr[i+2]) == 2:
        print(ndecr[i])

for i in ndecr:
    ele = i
    ndecr.remove(i)
    for j in ndecr:
        if ele[:-1] == j:
            print(j)   

for i in ndecr:
    ele = i
    ndecr.remove(i)
    for j in ndecr:
        if ele[:-2] == j:
            print(i)

请帮助我实现输出的方法。

【问题讨论】:

  • 您到底想在输出中“排序”和“分组”什么?我想我了解您想要比较列表列表中的所有列表并输出比较列表的索引以及长度差异,但我不确定您希望如何对输出进行排序或分组。

标签: python arrays python-3.x list nested-lists


【解决方案1】:

IIUC,假设列表的总数很小,因此 len(lists)^2 仍然很小,类似于

from itertools import combinations

# sort by length but preserve the index
ax = sorted(enumerate(a), key=lambda x: len(x[1]))

done = []

for (i0, seq0), (i1, seq1) in combinations(ax, 2):
    if seq1[:len(seq0)] == seq0 or seq1[-len(seq0):] == seq0:
       done.append((i1, i0, len(seq1)-len(seq0)))

给我

In [117]: sorted(done)
Out[117]: 
[(0, 2, 1),
 (3, 1, 1),
 (3, 5, 2),
 (3, 6, 1),
 (4, 1, 2),
 (4, 7, 2),
 (6, 5, 1),
 (7, 8, 1),
 (9, 10, 2)]

这与您的输出相匹配,但为了订单,并且您 (4, 7, 2) 列出了两次。

seq1[:len(seq0)] == seq0 

是“seq1 是否以 seq0 开头?”条件,和

seq1[-len(seq0):] == seq0

是“seq1 是否以 seq0 结尾?”条件。

【讨论】:

  • 这是一个错误。 (4,7,2) 重复两次。编辑并删除它。
  • 我需要学习更多模块,我必须通过枚举来做到这一点,我很嫉妒
【解决方案2】:

嗯,我确信这可以更有效地完成,但我所做的是创建原始列表的副本,其中每个项目在任一端缩短一到两个,然后比较这些项目并返回索引与相应的它们的长度不同,它有效,但它相当大,我会看到减少它

l1 = a[:]

tups = []
for idx, item in enumerate(l1):
    for x, i in enumerate(a):
        if sorted(item[:-1]) == sorted(i):
            tups.append((idx, x, 1))
        elif sorted(item[:-2]) == sorted(i):
            tups.append((idx, x, 2))
        elif sorted(item[1:]) == sorted(i):
            tups.append((idx, x, 1))
        elif sorted(item[2:]) == sorted(i):
            tups.append((idx, x, 2))

print(tups)
[(0, 2, 1), (3, 1, 1), (4, 7, 2), (3, 6, 1), (6, 5, 1), (7, 8, 1), (3, 5, 2), (4, 1, 2), (9, 10, 2)]

【讨论】:

    【解决方案3】:

    编辑(原文如下):

    现在,我可能会更好地理解您(感谢@vash_the_stampede 的澄清评论)。这种方法嵌套了几个循环来比较列表列表中的每个列表,并确定一个是否是另一个的子集。然后,如果比较列表是超集/子集,它会创建一个元组的输出列表,每个元组都包含两个比较列表的索引,它们首先排序最长,以及这些比较列表的长度差异。

    重要提示:此方法不比较列表顺序,因此它可能会提供您可能不想要的输出,例如 [1,2,4,5] 是长度差为 1 的 [1,2,3,4,5] 的子集。或者,特定于您的示例,此方法与您的示例输出相比,输出一个额外的元组,因为在索引 8 处的 [3,4,5,6] 是在索引 4 处的 [2,3,4,5,6,7,8] 的子集,长度差为 3。我认为来自 @DSM 的答案可以解决这个问题,所以它可能更接近你的需要。

    当前数据集的示例输出:

    a = [[1,2,3,4,5], [4,5,6,7,8], [1,2,3,4], [4,5,6,7,8,9], [2,3,4,5,6,7,8], [6,7,8,9], [5,6,7,8,9], [2,3,4,5,6], [3,4,5,6], [11,12,13,14,15], [13,14,15]]
    
    output = []
    for i in range(len(a)):
        for j in range(i + 1, len(a)):
           if set(a[i]).issubset(a[j]) or set(a[i]).issuperset(a[j]):
               diff = abs(len(a[i]) - len(a[j]))
               if len(a[i]) > len(a[j]):
                   output.append((i, j, diff))
               else:
                   output.append((j, i, diff))
    
    print(output)
    
    # OUTPUT
    # [(0, 2, 1), (3, 1, 1), (4, 1, 2), (3, 5, 2), (3, 6, 1), (4, 7, 2), (4, 8, 3), (6, 5, 1), (7, 8, 1), (9, 10, 2)]
    

    原文:

    如果我对您的理解正确,那么您可以嵌套几个循环来比较列表列表中的每个列表。然后,创建一个元组的输出列表,每个元组包含两个比较列表的索引以及这些比较列表的长度差异。例如:

    a = [[1,2,3,4,5], [4,5,6,7,8], [1,2,3,4], [4,5,6,7,8,9], [2,3,4,5,6,7,8], [6,7,8,9], [5,6,7,8,9], [2,3,4,5,6], [3,4,5,6], [11,12,13,14,15], [13,14,15]]
    
    output = []
    for i in range(len(a)):
        for j in range(i + 1, len(a)):
           diff = abs(len(a[i]) - len(a[j]))
           output.append((i, j, diff))
    
    print(output)
    
    # OUTPUT
    # [(0, 1, 0), (0, 2, 1), (0, 3, 1), (0, 4, 2), (0, 5, 1), (0, 6, 0), (0, 7, 0), (0, 8, 1), (0, 9, 0), (0, 10, 2), (1, 2, 1), (1, 3, 1), (1, 4, 2), (1, 5, 1), (1, 6, 0), (1, 7, 0), (1, 8, 1), (1, 9, 0), (1, 10, 2), (2, 3, 2), (2, 4, 3), (2, 5, 0), (2, 6, 1), (2, 7, 1), (2, 8, 0), (2, 9, 1), (2, 10, 1), (3, 4, 1), (3, 5, 2), (3, 6, 1), (3, 7, 1), (3, 8, 2), (3, 9, 1), (3, 10, 3), (4, 5, 3), (4, 6, 2), (4, 7, 2), (4, 8, 3), (4, 9, 2), (4, 10, 4), (5, 6, 1), (5, 7, 1), (5, 8, 0), (5, 9, 1), (5, 10, 1), (6, 7, 0), (6, 8, 1), (6, 9, 0), (6, 10, 2), (7, 8, 1), (7, 9, 0), (7, 10, 2), (8, 9, 1), (8, 10, 1), (9, 10, 2)]
    

    【讨论】:

    • 查看说明和输出,他只想要由具有相同值但略有不同的列表组成的元组,他不会对所有列表进行所有比较
    • @vash_the_stampede 从目前的问题来看,您可能比我更清楚地了解 OP 想要什么。我在重新阅读后发表了一条评论,要求进一步澄清,因为我现在对 OP 的目标有点模糊。
    • 例如 a[0] 类似于 a[2] 但相差一个项目 5 所以这两个索引成为一个元组 (0,2,1) ,1 是他们不同的项目数量跨度>
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-26
    • 1970-01-01
    • 2014-03-07
    • 1970-01-01
    • 2016-10-27
    • 2021-09-15
    相关资源
    最近更新 更多