【问题标题】:Python - Intersectiing stringsPython - 相交的字符串
【发布时间】:2012-03-16 11:36:54
【问题描述】:

尝试编写一个 for 函数,该函数接受两个字符串并按照它们在第一个字符串中出现的顺序返回相交的字符。

这是我尝试过的:

def strIntersection(str1, str2):
    for i in str1:
        str3 = ''
        str3 = str3.join(i for i in str1 if i in str2 not in str3)
    return str3

str1 = 'asdfasdfasfd'
str2 = 'qazwsxedc'

strIntersection(str1,str2)

=> 'asdasdasd'

但是我只希望交集字符按第一个字符串的顺序出现一次,即。 'asd'

谁能帮忙?

我在其他论坛上发现了一些类似的问题,但解决方案似乎都涉及列表,而我希望我的输出是一个字符串

【问题讨论】:

    标签: python string intersection


    【解决方案1】:

    反过来检查是否发生以控制订单,并且不要发出您已经发出的字符:

    def strIntersection(s1, s2):
      out = ""
      for c in s1:
        if c in s2 and not c in out:
          out += c
      return out
    

    当然,您可以将其重写为列表理解,但我发现这更容易理解。

    对于您的测试数据,我们得到:

    >>> strIntersection('asdfasdfasfd' , 'qazwsxedc')
    'asd'
    

    【讨论】:

    • 谢谢!这当然更容易理解。我现在意识到我尝试使用 ''join() 使事情复杂化了
    • ''.join 是惯用的,一点也不复杂。然而,在循环中使用它会错过重点。实际上,OP 代码中的 for-loop 完全没用;它只会导致真正的工作 - str3 = str3.join(i for i in str1 if i in str2 not in str3) 被执行多次,每次结果相同,并且每次都丢弃结果,但最后一次。
    • 您实际上无法将此特定算法重写为列表理解 - 至少在不调用一些非常可疑的未记录内容的情况下不能 - 因为过滤步骤 c in s2 and c not in out 取决于到目前为止的部分结果,无法访问(除非通过非常可疑的无证材料)。
    • 我刚刚评论说用列表替换 out 会加快速度,但后来做了一些 timeit 测试并确定它们没有,所以我删除了我的旧评论。我的时间显示这个解决方案每个循环使用 10.7 微秒,卡尔斯解决方案每个循环使用 16.7 微秒,而我修改后的 out = []return "".join(out) 解决方案每个循环使用 18.5 微秒。
    • 针对这些特定的字符串,或者针对什么测试数据?基于集合的方法可能需要相当长的字符串才能显示出优势。
    【解决方案2】:

    您需要一个由str1str2 共有的唯一字符组成的字符串,按照它们在str1 中出现的顺序排列。

    唯一性和共性意味着集合操作:也就是说,我们正在寻找同时出现在 str1 和 str2 中的字符集。集合基本上是无序的,但我们可以通过根据字符在str1 中首次出现的“索引”对字符进行排序来重新排序数据。然后从排序后的序列中创建一个字符串就很简单了。

    综合起来,我们得到:

    ''.join(sorted(set(str1) & set(str2), key = str1.index))
    

    【讨论】:

      【解决方案3】:

      您可以使用 python 集合http://docs.python.org/library/stdtypes.html#set 来执行此操作,如下所示:

      >>> set("asdfasdfasfd") & set("qazwsxedc")
      set(['a', 's', 'd'])
      

      【讨论】:

        【解决方案4】:

        最简单的方法是在 python 中使用集合

        >>> a='asdfasdfasfd'
        >>> b='qazwsxedc'
        >>> set(a).intersection(b)
        set(['a', 's', 'd'])
        

        【讨论】:

        • 这复制了现有的答案,不提供 OP 要求的排序。
        【解决方案5】:

        如果您修正了第四行的错字,您当前的脚本似乎应该这样做:

        str3 = str3.join(i for i in str1 if i in str2 not in str3)
        

        应该是

        str3 = str3.join(i for i in str1 if i in str2 and i not in str3)
        

        我不建议为此 simpy 使用套装,因为它们不保证顺序。您的脚本也可能会更快。

        【讨论】:

        • 我很确定 OP 的真正含义是 (i for i in str1 if i in str2 and i not in str3)。除非这不起作用,因为需要与之比较的str3 尚未构建。他试图同时使用 for 循环和推导式,弄乱了他的逻辑。至于性能,我当然希望基于set 的方法对于长字符串来说要快得多。
        • @Karl:是的,你是对的,我会更新我的答案。但是与str3比较应该没有问题,因为它只需要检查已经构建的部分。
        • 问题是str3 不是“已经构建的部分”。要么在循环中执行此代码,要么不执行。如果你不这样做,那么str3 将给出一个 UnboundLocalError - 你试图引用你正在分配的东西。如果你这样做了,那么拥有join 和理解是没有意义的,因为你只想考虑当前字符与已经找到的相交字符,而不是整个字符串。
        • @Karl:我今天真的没醒!阅读时我错过了str3 = ''str3.join(...)。我以为它在一个循环中。
        【解决方案6】:
        def str_intersection(str1, str2):
            common_letters = set(str1) & set(str2)
            str3 = ''
            for c in str1:
                if (c in common_letters) and (c not in str3):
                    str3 += c
            return str3
        

        【讨论】:

          猜你喜欢
          • 2013-11-25
          • 2018-07-10
          • 1970-01-01
          • 2021-06-13
          • 2019-03-17
          • 2016-07-15
          • 2019-02-21
          • 1970-01-01
          • 2013-01-10
          相关资源
          最近更新 更多