如果不满足条件,则删除列表列表中的列表

Removing a list in a list of lists if a condition not satisfied

我有一个列表列表。如果列表中的值与先前列表的交集长度超过一个,我想删除列表。

例如

A=[(1,2,3,4), (2,3,5,6),(1,7,8,9),(2,4,6,8)]

我们需要保留第一个列表,因为没有之前的列表。我们删除 (2,3,5,6),因为它与先前列表的交集是 (2,3),它的长度是 2。我们保留 (1,7,8,9) 并同样删除 (2,4,6,8)

最后我们的列表应该变成 B=[(1,2,3,4), (1,7,8,9)]

通常情况下,这段代码应该可以满足您的需求

A=[(1,2,3,4), (2,3,5,6),(1,7,8,9),(2,4,6,8)]

B = []

precedent = []
for list_ in A:
    intersection = 0

    for num in list_:
        if num in precedent:
            intersection += 1

    if intersection < 1:
        B.append(list_)

    precedent = list_

我认为这是您可以尝试的一种方法。

def intersection_length(lst1, lst2):
    intersection_list = [value for value in lst1 if value in lst2]
    return len(intersection_list)

def filter_lists(lists):
    filtered_lists = []
    filtered_lists.append(lists[0])
    del lists[0]

    for list_item in lists:
        is_ok = True
        for prev_list in filtered_lists:
            if intersection_length(list_item, prev_list) > 1:
                is_ok = False
                continue
        if is_ok:
            filtered_lists.append(list_item)
    return filtered_lists

def main():
    filtered = filter_lists(
        [(1, 2, 3, 4), (2, 3, 5, 6), (1, 7, 8, 9), (2, 4, 6, 8)]
    )
    print(filtered)

if __name__ == "__main__":
    main()

这是一个可能的解决方案:

A=[(1,2,3,4),(2,3,5,6),(1,7,8,9),(2,4,6,8)]
B=[]

# iterate over sublists a of the list A
for a in A:
    # define and reset the intersections counter
    intersections=0
    # iterate of sublists b of B
    for b in B:
        # reset the intersections counter
        intersections=0
        # iterate over the numbers num of sublist a
        for num in a:
            # perform checks
            if num in b:
                intersections+=1
            if intersections>1:
                break
        # break the iteration over sublists b if check fulfilled
        if intersections>1:
            break
    # Append a to the subset B only if intersection were not > 1 
    if intersections>1:
        continue
    B.append(a)
    # repeat
#B now contains the result...
print(B)

这里是一个直接的实现:

A = [(1,2,3,4), (2,3,5,6), (1,7,8,9), (2,4,6,8)]

B = []
intersect = 0
for a in A:
    for b in B:
        intersect = 0
        for num in b:
            if num in a:
                intersect += 1
        if intersect > 1:
            break
    if intersect < 2:
        B.append(a)

给出:

B = [(1, 2, 3, 4), (1, 7, 8, 9)]

一个可能更有效的解决方案,以防您拥有(并保留)更多但仍然很短的元组。这将检查列表中的数字对。如果 none 对出现在已保留的元组中,则保留当前元组 a

from itertools import combinations

A = [(1,2,3,4), (2,3,5,6), (1,7,8,9), (2,4,6,8)]

B = []
B_pairs = set()
for a in A:
    pairs = set(map(frozenset, combinations(a, 2)))
    if not B_pairs & pairs:
        B.append(a)
        B_pairs |= pairs
print(B)

Ouss 解决方案的一些基准测试,因为他们提出了这个问题:

With 5000 tuples, 2553 of which are kept:
  23 ms  Kelly
2853 ms  Ouss

With 5000 tuples, 2540 of which are kept:
  21 ms  Kelly
2776 ms  Ouss

With 5000 tuples, 2558 of which are kept:
  20 ms  Kelly
2685 ms  Ouss

基准代码(Try it online!):

from itertools import combinations

def Kelly(A):
  B = []
  B_pairs = set()
  for a in A:
    pairs = set(map(frozenset, combinations(a, 2)))
    if not B_pairs & pairs:
        B.append(a)
        B_pairs |= pairs
  return B

def Ouss(A):
  B=[]

  # iterate over sublists a of the list A
  for a in A:
    # define and reset the intersections counter
    intersections=0
    # iterate of sublists b of B
    for b in B:
        # reset the intersections counter
        intersections=0
        # iterate over the numbers num of sublist a
        for num in a:
            # perform checks
            if num in b:
                intersections+=1
            if intersections>1:
                break
        # break the iteration over sublists b if check fulfilled
        if intersections>1:
            break
    # Append a to the subset B only if intersection were not > 1 
    if intersections>1:
        continue
    B.append(a)
    # repeat
  #B now contains the result...
  return B

from timeit import timeit
from random import sample

A = [tuple(sample(range(100), 4)) for _ in range(500)]
print(Kelly(A) == Ouss(A), len(Kelly(A)))

for _ in range(3):
    A = [tuple(sample(range(400), 4)) for _ in range(5000)]
    print(f'With {len(A)} tuples, {len(Kelly(A))} of which are kept:')
    for func in Kelly, Ouss:
        time = timeit(lambda: func(A), number=1)
        print('%4d ms ' % (time * 1e3), func.__name__)
    print()