【问题标题】:Remove difference but keeping order and duplicates in python lists删除差异但在 python 列表中保持顺序和重复
【发布时间】:2016-11-26 21:35:15
【问题描述】:

使用 3.x 版本 - 想知道解决以下问题的最简单和原生的方法:

示例列表:

listA = [1, 2, 3, 66, 0]
listB = [0, 0, 1, 2, 3, 66, 0, 99, 0, 3]

如何消除两个列表之间的差异,以使新的 listC 与 listA 的顺序完全相同?

所以使用上面的例子 listC 应该等于[1, 2, 3, 66, 0]

列表 A 可能大于列表 B,另一个条件是列表 A 永远不会有重复编号,而列表 B 可能有重复。

我要解决的慈善俱乐部练习是:

林黛的大脑测试:

请编写一个程序,如果 B 的元素按照它们在 B 中出现的顺序出现在 A 中,则打印“YES”,但不一定是连续的。否则程序应该打印“NO”。

林黛的奖金测试:

如果 B 的元素出现在 A 中,请编写一个程序打印 'YES' 按顺序出现在 B 中并连续出现。

显然,如果有人喜欢这个挑战,那么请发布完整的程序来解决这两个问题。

【问题讨论】:

  • Linday 的大脑测试只是询问 B 是否是 A 的 子序列,对吧?
  • 你写:“列表 B 永远不会有重复的数字,不像列表 A whist [sec] 可能有重复。”:但是你给出的例子违反了这个条件:listB 在您的示例中有重复项。
  • 我已经纠正了这个错误,但 Trincot 您的解决方案在第一部分有效,谢谢您的布局非常好而且简单。您能否重新发布奖金问题解决方案
  • 我正在重写一些。完成后将重新发布;-) 但是:林赛大脑/奖励问题似乎表明 A 通常比 B 有更多的元素。如果 B 的元素多于 A,那么如果我读得很好,那么两者都不能返回“是”,因为B 的 每个 元素必须出现在 A 中,并保持相同的顺序。我误会了吗?
  • 另一个问题。 Lindey 测试说 "..prints 'YES' if B 的元素出现在 A.."。这是否意味着 B 的 所有 元素?还是一个就够了?但是如果一个就足够了,那么要求它在 A 中以相同的顺序出现是没有意义的。如果一个足够了,算法可以停止检查其他任何内容,而只打印“YES”。还是应该进一步检查,如果 B 中有第二个元素出现在 A 中,但顺序错误,它仍然应该打印“NO”?我觉得描述令人困惑。

标签: python python-3.x


【解决方案1】:

另一种稍微作弊的方法是使用带有in 运算符的字符串。如果将每个列表都转换成字符串,可以快速查看A是否是B的子串,顺序相同,连续。

def aInB(listA, listB):
    str_a = "," + ",".join([str(c) for c in listA]) + ","
    # ',1,2,3,66,0,'
    str_b = "," + ",".join([str(c) for c in listB]) + ","
    # ',0,0,1,2,3,66,0,99,0,3,'

    return str_a in str_b
# True

现在这仅在 A 的长度小于 B 的情况下才有效,但根据问题的定义,这听起来总是正确的。由于@stefanpochmann 在 cmets 中指出的问题,额外的逗号是必要的。

打印“YES”和“NO”非常简单:

if aInB(listA, listB):
   print("YES")
else:
   print("NO")

对于非连续方法,我相信您必须采用其中一种迭代方法。这个解决方案在这里只是简单地提供一种替代的思考方式是“A in B”。

编辑:我情不自禁,所以这里有一种交互式方法,可能有点矫枉过正,但也许你会发现它更容易理解(你永远不知道)。

def aInB(listA, listB):
   # if listA is empty, don't even bother
   if not listA:
      return False

   # build a dictionary where each key is a character in listA
   # and the values are a list containing every index where that character
   # appears in listB
   occurences = {c:[i for i,e in enumerate(listB) if e==c] for c in listA}

   # now we are going to walk through listA again
   # but this time we are going to use our `occurences` dictionary
   # to verify that the elements appear in order
   last_index = 0
   for i,e in enumerate(listA):
     # if the character `e` never appears in listB
     # then it will have an empty list
     # and we can return False
     if not occurences[e]:
         return False

     # now the next possible index for the next character in listA
     # must be *greater* than the index of the last character we found
     # if no such index exists, then listA is not contained within listB
     # if it is, we update the last seen index
     next_possible_index = [x for x in occurences[e] if x > last_index]
     if not next_possible_index:
         return False
     last_index = next_possible_index[0]

   # if we make it out of the for loop
   # then all is well, and listA is contained in listB
   # but not necessarily consequtively 
   return True

【讨论】:

  • 失败例如aInB([1], [11])。
  • 好收获。不过有一个解决方法。
【解决方案2】:
def f(l1, l2):
    i1 = 0
    i2 = 0

    while i1 < len(l1) and i2 < len(l2):
        if l1[i1] == l2[i2]:
            i1 += 1
            i2 += 1
        else:
            i2 += 1

    if i1 == len(l1):
        return True
    return False

listA = [1, 2, 3, 66, 0]
listB = [0, 0, 1, 2, 3, 66, 0, 99, 0, 3]

print (f(listA, listB))
# will print true

【讨论】:

  • 好吧,你显然是个聪明人——我如何在不创建这个函数的情况下在同一个程序中实际使用它?
  • 对不起,这只是解决应该打印'YES'或'NO'的问题的想法
  • 为什么不想创建函数?
  • 我觉得如果要去掉这个函数,只要去掉第一行,把return改成一个打印语句
  • 谢谢 - 你的看起来太复杂了!我只是复制它出错了!
猜你喜欢
  • 2010-12-05
  • 1970-01-01
  • 2010-10-03
  • 2012-07-21
  • 1970-01-01
  • 1970-01-01
  • 2021-07-26
  • 2021-12-23
相关资源
最近更新 更多