【问题标题】:Python - Remove any element from a list of strings that is a substring of another elementPython - 从字符串列表中删除作为另一个元素的子字符串的任何元素
【发布时间】:2014-03-10 07:43:43
【问题描述】:

所以从一个字符串列表开始,如下

string_list = ['rest', 'resting', 'look', 'looked', 'it', 'spit']

我想从列表中删除作为另一个元素的子字符串的任何元素,例如给出结果...

string_list = ['休息','看着','吐']

我有一些代码可以实现这一点,但它非常难看,而且可能是不必要的复杂。有没有简单的方法在 Python 中做到这一点?

【问题讨论】:

  • 让我们看看丑陋的版本。这将是一个很好的……破冰船
  • 从来没有看到有人在问题中嘲笑他们的代码
  • 前几天我问了一个类似的问题stackoverflow.com/questions/21653585/…
  • 可以在here 找到一个类似的问题,可能会提供更高效的解决方案

标签: python string list substring


【解决方案1】:

这是一种非最佳方式,仅在列表较小时使用:

for str1 in string_list:
    for str2 in string_list:
        if str1 in str2 and str1 != str2:
            string_list.remove(str1)

【讨论】:

    【解决方案2】:

    这是另一种方法。假设您有一个排序列表开始,并且您不必就地进行筛选,我们可以一次选择最长的字符串:

    string_list = sorted(string_list)
    sieved = []
    for i in range(len(string_list) - 1):
        if string_list[i] not in string_list[i+1]:
            sieved.append(string_list[i])
    

    【讨论】:

      【解决方案3】:

      第一个构建块:子字符串。

      您可以使用in查看:

      >>> 'rest' in 'resting'
      True
      >>> 'sing' in 'resting'
      False
      

      接下来,我们将选择创建新列表的简单方法。我们将一项一项地添加到新列表中,检查它们是否是子字符串。

      def substringSieve(string_list):
          out = []
          for s in string_list:
              if not any([s in r for r in string_list if s != r]):
                  out.append(s)
          return out
      

      你可以通过排序来加快速度,减少比较次数(毕竟,较长的字符串永远不可能是较短/等长字符串的子字符串):

      def substringSieve(string_list):
          string_list.sort(key=lambda s: len(s), reverse=True)
          out = []
          for s in string_list:
              if not any([s in o for o in out]):
                  out.append(s)
          return out
      

      【讨论】:

      • 是的。刚刚修好它们。过失。
      【解决方案4】:

      这是一个可能的解决方案:

      string_list = ['rest', 'resting', 'look', 'looked', 'it', 'spit']
      def string_set(string_list):
          return set(i for i in string_list 
                     if not any(i in s for s in string_list if i != s))
      
      print(string_set(string_list))
      

      打印出来:

      set(['looked', 'resting', 'spit'])
      

      注意我创建了一个集合(使用生成器表达式)来删除可能重复的单词,因为看起来顺序并不重要。

      【讨论】:

        【解决方案5】:

        这是执行此操作的有效方法(相对于上述解决方案;)),因为这种方法大大减少了列表元素之间的比较次数。如果我有一个很大的列表,我肯定会选择这个,当然你可以把这个解决方案变成一个 lambda 函数,让它看起来很小:

        string_list = ['rest', 'resting', 'look', 'looked', 'it', 'spit']
        for item in string_list: 
          for item1 in string_list:
            if item in item1 and item!= item1:
              string_list.remove(item)
        
        print string_list
        

        输出:

        >>>['resting', 'looked', 'spit']
        

        希望对你有帮助!

        【讨论】:

          【解决方案6】:

          另一个班轮:

          [string for string in string_list if len(filter(lambda x: string in x,string_list)) == 1]
          

          应该是相当易读的,只是不是那种pythonic。

          【讨论】:

          • 注意python 3,过滤器返回一个迭代器,所以这可能会引发TypeError: object of type 'filter' has no len()。只需要将filterlist 包装起来:len(list(filter(lambda x: string in x,string_list)))
          • 另外,如果 string_list 哈希重复,例如['apple', 'apple']。这将返回一个空列表,而不是 ['apple']。这种行为可能需要也可能不需要。
          【解决方案7】:

          这是一个可以满足您的需求的单线:

          filter(lambda x: [x for i in string_list if x in i and x != i] == [], string_list)
          

          例子:

          >>> string_list = ['rest', 'resting', 'look', 'looked', 'it', 'spit']
          >>> filter(lambda x: [x for i in string_list if x in i and x != i] == [], string_list)
          ['resting', 'looked', 'spit']
          

          【讨论】:

            【解决方案8】:

            这是一种方法:

            def find_unique(original):
                output = []
            
                for a in original:
                    for b in original:
                        if a == b:
                            continue     # So we don't compare a string against itself
                        elif a in b:
                            break
                    else:
                        output.append(a) # Executed only if "break" is never hit
            
                return output
            
            if __name__ == '__main__':
                original = ['rest', 'resting', 'look', 'looked', 'it', 'split']
                print find_unique(original)
            

            它利用了这样一个事实,即我们可以通过使用in 运算符轻松检查一个字符串是否是另一个字符串的子字符串。它基本上遍历每个字符串,检查它是否是另一个字符串的子字符串,如果不是,则将其自身附加到输出列表中。

            这会打印出['resting', 'looked', 'split']

            【讨论】:

              猜你喜欢
              • 2020-04-05
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-10-01
              • 1970-01-01
              • 1970-01-01
              • 2019-08-03
              • 2013-07-15
              相关资源
              最近更新 更多