循环浏览要更新的列表

时间:2019-12-02 15:53:25

标签: python list itertools

我正在处理两列。一个有几个单独的数字,另一个有和。我想匹配list1和list2。在每次迭代中,我都会删除匹配的数字。不一定所有数字都匹配,但我想获得尽可能多的数字。我该如何确保循环继续迭代,但在完成所有匹配后终止?

理想情况下,在下面的示例中,我希望得到这样的结果:

[5,6],11 \ n [2,3],5

当然,如果整个方法不正确,请随时提出建议。

谢谢您的帮助。

import itertools

list1=[5,6,2,3,8,7]
list2=[11,5]

combos=list(itertools.combinations(list1, 2))

for i in range(len(list1)):
    if sum(combos[i]) in list2:
        list1.remove(combos[i][0])
        list1.remove(combos[i][1])
        list2.remove(sum(combos[i]))
        combos=list(itertools.combinations(list1, 2))
        print(combos[i])

2 个答案:

答案 0 :(得分:0)

这只会带来一场比赛,但这并不是最好的一场比赛:

    import itertools

    list1=[5,6,2,3,8,7]
    list2=[11,5]

    combos=list(itertools.combinations(list1, 2))
    result=[]
    for i in range(len(combos)):
        if sum(combos[i]) in list2 and (combos[i][0] in list1 and combos[i][0] in list1 ):
            result.append(combos[i])
            list1.remove(combos[i][0])
            list1.remove(combos[i][1])
            list2.remove(sum(combos[i]))

    print(result)

    #Output: [(5, 6), (2, 3)]

对于下面的输入,它只会找到一些匹配项,而不是最多的匹配项(取决于组合检查的顺序):

    list1=[5,6,2,8,3,7]
    list2=[11,5,10,15]
    # Output: [(5, 6), (2, 8)]

    list1=[5,6,2,3,8,7]
    list2=[11,5,10,15]
    # Output: [(5, 6), (2, 3), (8, 7)]

答案 1 :(得分:0)

只要您的问题不够明确,我认为:

  • 有两个类列表存储,其中元素(int)的未排序顺序
  • 在两个存储中
  • 元素可能会重复
  • 每个组合,可以通过特殊功能(求和)将“ 任意长度”从第一个序列“ ”中“匹配”到第二个存储中的对应元素;
  • 应该找到
  • 尽可能多的(或可能是所有)此类匹配项,并在找到后(通过产量或打印方式)立即进行检索);
  • 从两个存储中找到
  • 与这些匹配项对应的所有唯一元素后,应立即删除
  • 允许每个存储创建个副本
  • 匹配算法应该有限

提议的解决方案基于这些假设,并且几乎可以满足所有这些假设。但是,如果要具体化条件,则可以显着简化-确切的存储类型是什么?如果数据类型可以是collections.dequeset,那就太好了-从列表对象中删除元素是很昂贵的事情。另外,如果您的数据应该更新-应该何时更新(在搜索匹配项时-或之后)?数据中是否有重复的元素?是否可以创建输入存储的副本?如果可以,这种副本的最大数量是多少?搜索匹配项时是否可以对存储进行其他任何更改?在存储空间变空后算法应该停止吗?

from itertools import combinations, chain

def update_data_matches(data, matches, comb_lengths, get_match, discard_all, discard_all_from):
    # itertools.combinations operates with tuple-copy of any input data,
    # which type is not tuple. We need to create one copy explicitly
    # to minimize number of created copies:
    data_copy = tuple(data)
    if isinstance(comb_lengths, int):
        combs = combinations(data_copy, comb_lengths)
    else:
        combs = chain.from_iterable(combinations(data_copy, cl) for cl in comb_lengths)
    matches_copy = frozenset(matches)
    for comb in combs:
        if (possible_match := get_match(comb)) in matches_copy:
            discard_all(matches, possible_match)
            discard_all_from(data, comb)
            yield comb

def lst_discard_all(lst, element, i=0):
    try:
        while True:
            del lst[(i := lst.index(element, i))]
    except ValueError:
        return

def lst_discard_all_from(lst, elements):
    for i in range(len(lst)-1, -1, -1):
        if lst[i] in elements:
            del lst[i]

def lstset_discard_all(lst, element):
    try:
        lst.remove(element)
    except ValueError:
        return

def lstset_discard_all_from(lst, elements):
    for e in elements:
        try:
            lst.remove(e)
        except ValueError:
            continue

def update_lst_data_matches(*args, **kwargs):
    return update_data_matches(*args, discard_all=lst_discard_all,
                               discard_all_from=lst_discard_all_from, **kwargs)

def update_set_data_matches(*args, **kwargs):
    return update_data_matches(*args, discard_all=set.discard,
                               discard_all_from=set.difference_update, **kwargs)

def update_lstset_data_matches(*args, **kwargs):
    return update_data_matches(*args, discard_all=lstset_discard_all,
                               discard_all_from=lstset_discard_all_from, **kwargs)

在您的情况下:

data1 = [5,6,2,3,8,7]
data2 = [11,5]

for match in update_lstset_data_matches(data1, data2, 2, sum):
    print(f'{match=}', f'{sum(match)=}', f'{data1=}', f'{data2=}')

结果:

match=(5, 6) sum(match)=11 data1=[2, 3, 8, 7] data2=[5]
match=(2, 3) sum(match)=5 data1=[8, 7] data2=[]
match=(3, 8) sum(match)=11 data1=[7] data2=[]

示例2:找到具有所有长度组合的所有总和匹配项。相关问题https://en.wikipedia.org/wiki/Subset_sum_problem

data3 = {-7, -3, 66, -2, 5, 8}
data4 = {0, 13, -9, 4, 19}

for match in update_set_data_matches(data3, data4, range(1, len(data3)), sum):
    print(f'{match=}', f'{sum(match)=}', f'{data3=}', f'{data4=}')

结果:

match=(5, 8) sum(match)=13 data3={66, -7, -3, -2} data4={0, 4, 19, -9}
match=(-7, -2) sum(match)=-9 data3={66, -3} data4={0, 4, 19}
match=(5, -3, -2) sum(match)=0 data3={66} data4={4, 19}
match=(5, 8, -7, -2) sum(match)=4 data3={66} data4={19}

示例3:

data5 = [11, 123, 3, 66, -2, 11, 8, 66, 3.0, 3]
data6 = [0, 13, -9, 4.0, 123, 4, 19, 0]

for match in update_lst_data_matches(data5, data6, range(1, len(data5)), sum):
    print(f'{match=}', f'{sum(match)=}', f'{data5=}', f'{data6=}')

结果:

match=(123,) sum(match)=123 data5=[11, 3, 66, -2, 11, 8, 66, 3.0, 3] data6=[0, 13, -9, 4.0, 4, 19, 0]
match=(11, 8) sum(match)=19 data5=[3, 66, -2, 66, 3.0, 3] data6=[0, 13, -9, 4.0, 4, 0]
match=(11, 8) sum(match)=19 data5=[3, 66, -2, 66, 3.0, 3] data6=[0, 13, -9, 4.0, 4, 0]
match=(3, -2, 3.0) sum(match)=4.0 data5=[66, 66] data6=[0, 13, -9, 0]
match=(3, -2, 3) sum(match)=4 data5=[66, 66] data6=[0, 13, -9, 0]
match=(-2, 3.0, 3) sum(match)=4.0 data5=[66, 66] data6=[0, 13, -9, 0]