在列表中检查数字不是2个总和的总和

时间:2018-01-21 13:29:12

标签: python nested-loops continue

给定一个整数列表,我想检查第二个列表并从第一个列表中删除只能从第二个列表中的两个数字之和的那些列表。因此,鉴于a = [3,19,20]b = [1,2,17],我想要[3,19]

看起来像是一个带有两个嵌套循环的cinch - 除了我已经遇到breakcontinue命令。

以下是我所拥有的:

def myFunction(list_a, list_b):
    for i in list_a:
        for a in list_b:
            for b in list_b:
                    if a + b == i:
                        break
                    else:
                        continue
                    break
                else:
                    continue
            list_a.remove(i)
    return list_a

我知道我需要做什么,只是语法似乎不必要地混淆。有人能告诉我一个更简单的方法吗? TIA!

4 个答案:

答案 0 :(得分:4)

你可以这样做,

In [13]: from itertools import combinations
In [15]: [item for item in a if item in [sum(i) for i in combinations(b,2)]]
Out[15]: [3, 19]

combinations将在b中提供所有可能的组合,并获取总和列表。只需检查a

中的值

修改

如果您不想使用itertools为其编写功能。像这样,

def comb(s):
    for i, v1 in enumerate(s):
        for j in range(i+1, len(s)):
            yield [v1, s[j]]

result = [item for item in a if item in [sum(i) for i in comb(b)]]

答案 1 :(得分:1)

对代码的评论

  • 在迭代列表中删除元素时非常危险。也许您可以将要保留的项目附加到新列表中,然后返回。
  • 您当前的算法为O(nm^2),其中n的大小为list_am的大小为list_b。这是非常低效的,但是问题的良好开端。
  • 还有许多不必要的continuebreak语句,这些语句可能导致难以调试的复杂代码。
  • 您还将所有内容都放在一个功能中。如果将每个任务拆分为不同的功能,例如将一个功能专用于查找对,另一个用于检查list_alist_bO(n)的每个项目。这是一种将问题分解为较小问题并将其用于解决更大问题的方法。

总的来说,我认为你的功能做得太多了,通过分解问题可以将逻辑压缩成更简单的代码。

另一种方法:

由于我发现此任务很有趣,我决定自己尝试一下。我概述的方法如下所示。

1。您可以先使用散列检查列表是否在def check_pairs(lst, sums): lookup = set() for x in lst: current = sums - x if current in lookup: return True lookup.add(x) return False 时间内有一对给定的金额:

list_b

2。然后您可以使用此功能检查list_a中的任何对是否等于def remove_first_sum(list_a, list_b): new_list_a = [] for x in list_a: check = check_pairs(list_b, x) if check: new_list_a.append(x) return new_list_a 中迭代的数字总和:

list_a

其中list_b中的数字会导致def remove_first_sum(list_a, list_b): return [x for x in list_a if check_pairs(list_b, x)] 中的两个数字之和。

3。以上也可以用列表理解来编写:

>>> remove_first_sum([3,19,20], [1,2,17])
[3, 19]
>>> remove_first_sum([3,19,20,18], [1,2,17])
[3, 19, 18]
>>> remove_first_sum([1,2,5,6],[2,3,4])
[5, 6]

两者的工作原理如下:

O(n)

注意:总体而言,上述算法的时间复杂度为O(n),并不需要太复杂的任何事情。但是,这也会导致./install --auto-dotfiles额外的辅助空间,因为保留一组来记录已经看到的项目。

答案 2 :(得分:1)

您可以先创建所有可能的总和组合,然后过滤掉不属于该组合列表的元素

定义输入列表

>>> a = [3,19,20]
>>> b = [1,2,17]

接下来,我们将定义两个元素之和的所有可能组合

>>> y = [i+j for k,j in enumerate(b) for i in b[k+1:]]

接下来,我们将一个函数应用于列表a的每个元素,并检查它是否存在于上面计算的列表中。 map函数可以与if/else子句一起使用。如果else子句成功,map将产生None。为了满足这一需求,我们可以过滤列表以删除None

>>> list(filter(None, map(lambda x: x if x in y else None,a)))

以上操作将输出:

>>> [3,19]

您也可以将所有这些行合并为一行来编写一行,但我不推荐这样做。

答案 3 :(得分:0)

你可以尝试这样的事情:

a = [3,19,20]
b=  [1,2,17,5]

n_m_s=[]
data=[n_m_s.append(i+j) for i in b for j in b  if i+j in a]

print(set(n_m_s))

print("after remove")

final_data=[]
for j,i in enumerate(a):
    if i not in n_m_s:
        final_data.append(i)

print(final_data)

输出:

{19, 3}
after remove
[20]