【问题标题】:How to avoid redundancy and apply filter into string combination如何避免冗余并将过滤器应用于字符串组合
【发布时间】:2017-12-14 14:01:20
【问题描述】:

我想避免在字符串列表中的所有可能组合中出现冗余(例如,1122 在我的上下文中与 2211 相同,因此结果列表中应该只有一个或另一个)。

我还想在组合过程中应用过滤器。例如,我不想在结果中包含任何包含3 的字符串。

我应该如何处理这个逻辑?

这段代码在做组合

>>> keywords = [''.join(i) for i in itertools.product(['11', '22', '33'], repeat = 2)]
>>> keywords
['1111', '1122', '1133', '2211', '2222', '2233', '3311', '3322', '3333']

【问题讨论】:

  • 是否也应该跳过22223333
  • 也许循环并对每个字符串进行排序,如果排序后的字符串在新列表中不存在,则添加原始字符串:stackoverflow.com/questions/15046242/… 如果这看起来是您想要的正确方向,我可以写一个更好的答案去吧。
  • 应删除任何包含 3 的字符串
  • 如果你不想在输出中出现 3,你应该从 inputproduct 中过滤掉这些字符串。
  • repeat 总是 2 吗?

标签: python algorithm itertools


【解决方案1】:

根据您的实际数据,可能是一种更有效的方法,但下面的算法将起作用。我们通过简单的比较消除了重复项。我已经将'3'的检查放入一个函数中。这比直接在列表推导中执行稍慢,但它使代码更通用。

import itertools

bases = ['11', '22', '33', '44']

def is_ok(u, v):
    ''' Test if a u,v pair is permitted '''
    return not ('3' in u or '3' in v)

keywords = [u+v for u, v in itertools.product(bases, repeat = 2) if u <= v and is_ok(u, v)]

输出

['1111', '1122', '1144', '2222', '2244', '4444']
print(keywords)

【讨论】:

    【解决方案2】:

    同样可以通过过滤itertools.combinations_with_replacement:

    代码

    import itertools as it
    
    
    bases = ["11", "22", "33", "44"]
    
    [x+y for x,y in it.combinations_with_replacement(bases, 2) if "3" not in x+y]
    # ['1111', '1122', '1144', '2222', '2244', '4444']
    

    这个版本更通用,不依赖于比较数字字符串。


    详情

    the docs我们可以理解为什么会这样:

    combinations_with_replacement()的代码也可以表示为product()的子序列,在过滤了元素未按顺序排序的条目(根据它们在输入池中的位置)

    def combinations_with_replacement(iterable, r):
        pool = tuple(iterable)
        n = len(pool)
        for indices in product(range(n), repeat=r):
            if sorted(indices) == list(indices):
                yield tuple(pool[i] for i in indices)
    

    以这种方式,每个项目都与一个唯一索引相关联。当比较两个项目的索引时,仅使用排序组合来产生一个项目。剩余的索引如已经看到的那样被丢弃。

    (0, 0)
    (0, 1)
    (0, 2)
    (0, 3)
    (1, 0)                                         # discarded
    (1, 1)
    ...
    

    有关此工具与itertools.product 之间相似性的更多详细信息,请参阅the docs

    【讨论】:

      【解决方案3】:

      这应该做你想做的:

      import itertools
      
      def main():
      
          newkeywords = []
          keywords = ["".join(i) for i in itertools.product(["11", "22", "33"], repeat = 2)]
          for item in keywords:
              newitem = "".join(sorted(item))
              if "3" not in newitem and newitem not in newkeywords:
                  newkeywords.append(newitem)
          print(newkeywords)
      
      main()
      

      结果:

      ['1111', '1122', '2222']
      

      它创建一个新列表,如果该排序项(使 1122 与 2211 相同)存在或存在数字“3”,则不要将其添加到新列表中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-08-12
        • 2019-01-02
        • 1970-01-01
        • 2018-12-17
        • 2012-11-17
        • 2014-09-28
        • 2011-06-16
        相关资源
        最近更新 更多