【问题标题】:What is the best way to generate all possible three letter strings?生成所有可能的三个字母字符串的最佳方法是什么?
【发布时间】:2011-10-27 19:01:08
【问题描述】:

我正在生成所有可能的三个字母关键字e.g. aaa, aab, aac.... zzy, zzz 下面是我的代码:

alphabets = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']

keywords = []
for alpha1 in alphabets:
    for alpha2 in alphabets:
        for alpha3 in alphabets:
            keywords.append(alpha1+alpha2+alpha3)

能否以更流畅、更高效的方式实现此功能?

【问题讨论】:

    标签: python performance


    【解决方案1】:
    keywords = itertools.product(alphabets, repeat = 3)
    

    请参阅documentation for itertools.product。如果您需要字符串列表,只需使用

    keywords = [''.join(i) for i in itertools.product(alphabets, repeat = 3)]
    

    alphabets也不需要是列表,可以是字符串,例如:

    from itertools import product
    from string import ascii_lowercase
    keywords = [''.join(i) for i in product(ascii_lowercase, repeat = 3)]
    

    如果您只想要lowercase ascii letters,则可以使用。

    【讨论】:

    • 如果您想在不占用大量内存的情况下即时生成每个字符组合,可以将[''.join(i) for i in product(ascii_lowercase, repeat = 3)] 更改为(''.join(i) for i in product(ascii_lowercase, repeat = 3)) 并在for-in 循环中遍历每个字符组合跨度>
    • @DCIndieDev:更好的是,让它成为map(''.join, product(ascii_lowercase, repeat=3));它像生成器表达式一样是惰性的(在 Python 3 上),但在 CPython 参考解释器上,这要归功于 map 的工作方式(它应用函数,然后在产生结果之前立即释放参数),它启用了优化product 为每个结果重用相同的tuple,而不是每次都构建和丢弃一个(许多懒惰的tuple 生产者使用类似的优化,例如zip,仅当结果为@987654337 时才适用@-ed 或解压到名称)。
    【解决方案2】:

    您也可以使用 map 代替列表推导(这是 map 仍然比 LC 更快的情况之一)

    >>> from itertools import product
    >>> from string import ascii_lowercase
    >>> keywords = map(''.join, product(ascii_lowercase, repeat=3))
    

    列表理解的这种变体也比使用''.join更快

    >>> keywords = [a+b+c for a,b,c in product(ascii_lowercase, repeat=3)]
    

    【讨论】:

    • 使用join,如果您更改repeat 的值,则无需更改它——在这里添加一些关于过早优化的陈词滥调。
    • a+b+c 仅在您必须制作 3 个字母组合时才有效。
    【解决方案3】:
    from itertools import combinations_with_replacement
    
    alphabets = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z']
    
    for (a,b,c) in combinations_with_replacement(alphabets, 3):
        print a+b+c
    

    【讨论】:

    • 这实际上不一样。用两个字母试试——你会得到 26 个组合,a 作为第一个字母,然后是 25 个 b 等,直到只有 zzz 作为第一个字母。也就是说,您不会同时获得abba,或者使用OP 中的示例,您不会获得zzy,因为您已经获得了yzz
    【解决方案4】:
    chars = range(ord('a'), ord('z')+1);
    print [chr(a) + chr(b) +chr(c) for a in chars for b in chars for c in chars]
    

    【讨论】:

      【解决方案5】:

      您也可以通过简单的计算在没有任何外部模块的情况下完成此操作。
      PermutationIterator 就是您要搜索的内容。

      def permutation_atindex(_int, _set, length):
          """
          Return the permutation at index '_int' for itemgetter '_set'
          with length 'length'.
          """
          items = []
          strLength = len(_set)
          index = _int % strLength
          items.append(_set[index])
      
          for n in xrange(1,length, 1):
              _int //= strLength
              index = _int % strLength
              items.append(_set[index])
      
          return items
      
      class PermutationIterator:
          """
          A class that can iterate over possible permuations
          of the given 'iterable' and 'length' argument.
          """
      
          def __init__(self, iterable, length):
              self.length = length
              self.current = 0
              self.max = len(iterable) ** length
              self.iterable = iterable
      
          def __iter__(self):
              return self
      
          def __next__(self):
              if self.current >= self.max:
                  raise StopIteration
      
              try:
                  return permutation_atindex(self.current, self.iterable, self.length)
              finally:
                  self.current   += 1
      

      给它一个可迭代的对象和一个整数作为输出长度。

      from string import ascii_lowercase
      
      for e in PermutationIterator(ascii_lowercase, 3):
          print "".join(e)
      

      这将从“aaa”开始并以“zzz”结束。

      【讨论】:

        【解决方案6】:
        print([a+b+c for a in alphabets for b in alphabets for c in alphabets if a !=b and b!=c and c!= a])
        

        这会消除一个字符串中的重复字符

        【讨论】:

          【解决方案7】:

          我们可以在没有 itertools 的情况下通过使用两个函数定义来解决这个问题:

          def combos(alphas, k):
              l = len(alphas)
              kRecur(alphas, "", l, k)
          
          def KRecur(alphas, prfx, l, k):
              if k==0:
                  print(prfx)
              else:
                  for i in range(l):
                      newPrfx = prfx + alphas[i]
                      KRecur(alphas, newPrfx, l, k-1)
          

          使用两个函数来避免重置 alpha 的长度,第二个函数自我迭代,直到它达到 k 为 0 以返回该 i 循环的 k-mer。

          取自 Abhinav Ramana 在 Geeks4Geeks 上的解决方案

          【讨论】:

          • 注意:这是printing 结果,这使得它在编程上比实际创建它们的东西更有用,yields/returns 它们用于进一步处理,它使用递归(这意味着它对于k 的大值会爆炸;Python 的堆栈帧限制默认为 1000,并且它不进行尾递归优化)。
          【解决方案8】:

          好吧,我在考虑如何涵盖该主题时提出了该解决方案:

          import random
          
          s = "aei"
          b = []
          lenght=len(s)
          for _ in range(10):
              for _ in range(length):
                  password = ("".join(random.sample(s,length)))
                  if password not in b:
                      b.append("".join(password))
          print(b)
          print(len(b))
          

          请让我描述一下里面发生了什么:

          1. 导入随机,
          2. 用我们想要使用的字母创建一个字符串
          3. 创建一个空列表,我们将使用它来放入我们的组合
          4. 现在我们使用范围(我输入了 10,但对于 3 位数字可能会更少)
          5. 接下来使用带有列表和列表长度的 random.sample,我们将创建字母组合并将其加入。
          6. 在接下来的步骤中,我们将检查 b 列表中是否有该组合 - 如果有,则不会将其添加到 b 列表中。如果当前组合不在列表中,我们会将其添加到其中。 (我们正在比较最终的连接组合)。
          7. 最后一步是打印包含所有组合的列表 b 并打印可能组合的数量。 也许它不是清晰和最有效的代码,但我认为它有效......

          【讨论】:

          • 请解释这段代码为什么以及如何工作。
          • 当然 - 我已经编辑了我的帖子!谢谢!
          猜你喜欢
          • 1970-01-01
          • 2011-09-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-10-03
          相关资源
          最近更新 更多