【问题标题】:Enumerate all the sorted permutations of a list枚举列表的所有排序排列
【发布时间】:2020-06-15 10:48:12
【问题描述】:

假设一个列表A = ["Foo", "Buzz", "Fizz", "Bar"]。 当我们使用稳定排序算法按首字母排序时,我们得到

>>> sorted(A, key=lambda x: x[0])
['Buzz', 'Bar', 'Foo', 'Fizz']

不稳定排序可能会产生 4 种不同的结果:

['Bar', 'Buzz', 'Fizz', 'Foo']
['Bar', 'Buzz', 'Foo', 'Fizz']
['Buzz', 'Bar', 'Fizz', 'Foo']
['Buzz', 'Bar', 'Foo', 'Fizz']

如何生成任意列表的所有排列不稳定的排列?

【问题讨论】:

    标签: python sorting permutation combinatorics


    【解决方案1】:
    from collections import defaultdict
    from itertools import permutations, product, chain
    
    # Some data.
    xs = ['foo', 'buzz', 'fizz', 'bar', 'blort', 'doh', 'duh']
    
    # When you sort, you use a function to create the sort keys.
    # For example, sorting by first letter.
    def firstletter(x):
        return x[0]
    
    # Create a data structure mapping each unique sort key to all
    # corresponding values in the original data.
    #   'f': ['foo', 'fizz']
    #   'b': ['buzz', 'bar', 'blort']
    #   'd': ['doh', 'duh']
    k2xs = defaultdict(list)
    for x in xs:
        k2xs[firstletter(x)].append(x)
    
    # For each key, get the possible permutations.
    perms = [
        list(permutations(k2xs[k]))
        for k in sorted(k2xs)
    ]
    
    # We need the Cartesian product of those permutations.
    sorts_grouped = list(product(*perms))
    
    # And we want it flattened.
    sorts = [
        list(chain(*tups))         # Equivalent to [x for tup in tups for x in tup]
        for tups in sorts_grouped
    ]
    
    # Check.
    for ys in sorts:
        print(ys)
    

    输出:

    ['buzz', 'bar', 'blort', 'doh', 'duh', 'foo', 'fizz']
    ['buzz', 'bar', 'blort', 'doh', 'duh', 'fizz', 'foo']
    ['buzz', 'bar', 'blort', 'duh', 'doh', 'foo', 'fizz']
    ['buzz', 'bar', 'blort', 'duh', 'doh', 'fizz', 'foo']
    ['buzz', 'blort', 'bar', 'doh', 'duh', 'foo', 'fizz']
    ['buzz', 'blort', 'bar', 'doh', 'duh', 'fizz', 'foo']
    ['buzz', 'blort', 'bar', 'duh', 'doh', 'foo', 'fizz']
    ['buzz', 'blort', 'bar', 'duh', 'doh', 'fizz', 'foo']
    ['bar', 'buzz', 'blort', 'doh', 'duh', 'foo', 'fizz']
    ['bar', 'buzz', 'blort', 'doh', 'duh', 'fizz', 'foo']
    ['bar', 'buzz', 'blort', 'duh', 'doh', 'foo', 'fizz']
    ['bar', 'buzz', 'blort', 'duh', 'doh', 'fizz', 'foo']
    ['bar', 'blort', 'buzz', 'doh', 'duh', 'foo', 'fizz']
    ['bar', 'blort', 'buzz', 'doh', 'duh', 'fizz', 'foo']
    ['bar', 'blort', 'buzz', 'duh', 'doh', 'foo', 'fizz']
    ['bar', 'blort', 'buzz', 'duh', 'doh', 'fizz', 'foo']
    ['blort', 'buzz', 'bar', 'doh', 'duh', 'foo', 'fizz']
    ['blort', 'buzz', 'bar', 'doh', 'duh', 'fizz', 'foo']
    ['blort', 'buzz', 'bar', 'duh', 'doh', 'foo', 'fizz']
    ['blort', 'buzz', 'bar', 'duh', 'doh', 'fizz', 'foo']
    ['blort', 'bar', 'buzz', 'doh', 'duh', 'foo', 'fizz']
    ['blort', 'bar', 'buzz', 'doh', 'duh', 'fizz', 'foo']
    ['blort', 'bar', 'buzz', 'duh', 'doh', 'foo', 'fizz']
    ['blort', 'bar', 'buzz', 'duh', 'doh', 'fizz', 'foo']
    

    【讨论】:

      【解决方案2】:

      重构并略微优化FMc's solution

      from itertools import permutations, product, chain, groupby
      
      def sorted_permutations(iter, key=lambda x: x, reverse=False):
          # map each unique sort key to all
          # corresponding values in the original data
          key_groups = dict((k, tuple(v)) for k, v in
                            groupby(sorted(iter, key=key), key=key))
      
          # for each key, get the possible permutations
          perms = (
              permutations(key_groups[k])
              for k in sorted(key_groups, reverse=reverse)
          )
      
          # the Cartesian product of those permutations
          sorts_grouped = product(*perms)
      
          for parts in sorts_grouped:
              # flatten them
              yield list(chain(*parts))
      

      【讨论】:

        猜你喜欢
        • 2017-07-21
        • 1970-01-01
        • 2019-02-07
        • 1970-01-01
        • 1970-01-01
        • 2015-05-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多