【问题标题】:Python looping through specific element in listPython循环遍历列表中的特定元素
【发布时间】:2015-07-16 13:01:58
【问题描述】:

我有两个以下列方式列出的列表,我正在尝试以某种特定的方式比较它们:

a = [[18, 299, 559], [18, 323, 564], [18, 353, 564], [18, 391, 570], [18, 448, 570]]

b = [[18, 353, 564], [18, 299, 559], [18, 323, 564], [18, 391, 570], [18, 448, 570]]

我想要什么

我想按以下顺序将a 的每个元素与b 进行比较。

例如,在上述情况下,在a 的第一个元素[18, 299, 559] 等于b 的[18, 299, 559] 之后,循环将中断并且在新循环中a 的第二个元素@ 即[18, 323, 564] 将被比较从[18, 323, 564] 到b 及以后。

这里的要点是,新循环不应该从b 的第一个元素重新开始迭代,同时将a 的所有元素分别与第0 个索引的b 的所有元素进行比较。

P.S. 在此示例中,我不是要检查两个列表中是否存在元素,也不是要查找任何缺失的元素,这可以通过使用 set 方法轻松完成。这个逻辑仅供我自己了解

我尝试了什么

所有普通的嵌套循环方法如下:

for i in a:
    for j in b: #after break it would always start with first element in b
        if i == j:
            break

这里的问题是在每个break new i 与b 的第一个元素进行比较之后,而不是从与a 匹配的最后一个元素进行比较

我脑海中的想法是这样的:

for i in a:
    for j in b: 
        if i == j:
           print something
           save index of j 
           break

        in the next loop start comparing new i from this saved index of j                        

然而,我无法将这个想法放入代码中。

我知道这听起来很荒谬,但就循环而言,这样的事情可以在 python 中实现吗?欢迎所有想法和提示。

【问题讨论】:

  • 你试过continue而不是break吗?
  • @lanAuld 不,我没有。让我看看
  • zip
  • @LanAuld 尝试在上面的代码中用continue 替换break,但仍然没有得到我想要的。你能强调一下我应该如何使用它吗?
  • @MathiasEttinger 使用 zip 两个循环将以并行方式迭代。这只会逐行比较两个元素。

标签: python for-loop


【解决方案1】:

当然,您可以追踪您在b 中的进展情况。我将这个变量称为start_j,从那里开始允许在b 中进行比较:

a = [[18, 299, 559], [18, 323, 564], [18, 353, 564], [18, 391, 570], [18, 448, 570]]
b = [[18, 353, 564], [18, 299, 559], [18, 323, 564], [18, 391, 570], [18, 448, 570]]

start_j = 0

for i in range(len(a)):
    for j in range(start_j, len(b)):
        if a[i] == b[j]:
            print 'match found:', i, j
            start_j = j
            break

如果找到匹配的元素,start_j 将设置为最新的j,并且下一次内部循环(用于检查b 中的元素)从那里开始。

输出:

match found: 0 1
match found: 1 2
match found: 3 3
match found: 4 4

【讨论】:

  • 这太优雅了!我认为这会相当复杂
  • 这主要是您的想法(问题底部的代码)。唯一的区别是循环通过 0、1、2... 而不是元素本身 (for i in a),因此您可以显式访问您所在的索引。
  • 是的。这与它完全匹配。非常感谢。
【解决方案2】:

这个怎么样:

start_idx = 0
for i in a:
    for j_idx, j in enumerate(b[start_idx:], start=start_idx):
        if j==a:
            print 'Bingo!'
            start_idx = j_idx
            break

P.S range(len(a)) - 太丑了:)

【讨论】:

  • 它并没有那么难看,但是如果您使用的是 2.7,xrange is 是一个更好的选择...(比具体的范围)
  • 我觉得我的版本更快
【解决方案3】:

这里是如何在没有继续或喙的情况下做到这一点......

a = [[18, 299, 559], [18, 323, 564], [18, 353, 564], [18, 391, 570], [18, 448, 570]]

b = [[18, 353, 564], [18, 299, 559], [18, 323, 564], [18, 391, 570], [18, 448, 570]]

matches = []

for i in xrange(len(a)):
    for j in xrange(len(b)):
        if a[i] == b[j]:
            matches.append([i,j])

for match in matches: print(match)

【讨论】:

  • 我只是在尝试。谢谢亚伦。
  • 没问题,学习许多不同的做事方法总是很棒的。
  • 我从没想过要使用set(),但@Hai_Vu 提供了一个非常有趣的解决方案。
  • 是的,它直接列出了差异和缺失的元素。它很有用,但我对我提到的方法更好奇。我一直在努力实施,所以才被问到。
【解决方案4】:

根据您的描述:

附:在此示例中,我不是要检查两个列表中是否存在元素,也不是要查找任何缺失的元素,这可以通过使用 set 方法轻松完成。这个逻辑仅供我自己了解

我认为您正在尝试在两个列表之间进行一组比较。为什么不把它们变成集合呢?

aset = set(tuple(item) for item in a)
bset = set(tuple(item) for item in b)

print 'Items only in A:', aset - bset
print 'Items only in B:', bset - aset
print 'Items in common:', aset & bset

注意:我必须将每个子列表变成一个元组,因为列表不可散列,因此不能在集合中。

【讨论】:

  • 我知道这种方法,正如我在 P.S.但我想知道我们是否可以保存 j 的状态并将其用于进一步迭代。
猜你喜欢
  • 2018-07-11
  • 1970-01-01
  • 1970-01-01
  • 2011-08-20
  • 1970-01-01
  • 2018-09-05
  • 2015-11-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多