【问题标题】:Get all combinations of neighbour elements in list获取列表中相邻元素的所有组合
【发布时间】:2014-07-01 17:19:13
【问题描述】:

如果它们是邻居,是否可以获得元素的所有组合?
这是一个例子:

编辑:我想在字符串上使用它,而不仅仅是数字。例如:[Explain,it,to,me,please]

列表:

[0,1,2,3,4]

结果:

[0,1,2,3,4],
[0,1,2,3],
[1,2,3,4],
[0,1,2],
[1,2,3],
[2,3,4],
[0,1],
[1,2],
[2,3],
[3,4],
[0],
[1],
[2],
[3],
[4]

结果中不会有例如[0,2,3] 等,因为02 在上面的排序列表中不是邻居。

我尝试使用itertools.combinations,但它提供了所有组合。

【问题讨论】:

    标签: python list math combinations


    【解决方案1】:

    你可以这样做:

    >>> L = [0,1,2,3,4]
    >>> result = [L[i:j] for i in xrange(len(L)) for j in xrange(i + 1, len(L) + 1)]
    >>> pprint.pprint(result)
    [[0],
     [0, 1],
     [0, 1, 2],
     [0, 1, 2, 3],
     [0, 1, 2, 3, 4],
     [1],
     [1, 2],
     [1, 2, 3],
     [1, 2, 3, 4],
     [2],
     [2, 3],
     [2, 3, 4],
     [3],
     [3, 4],
     [4]]
    

    然后,按长度降序和升序排序:

    >>> result.sort(key=lambda x: (-len(x), x))
    >>> pprint.pprint(result)
    [[0, 1, 2, 3, 4],
     [0, 1, 2, 3],
     [1, 2, 3, 4],
     [0, 1, 2],
     [1, 2, 3],
     [2, 3, 4],
     [0, 1],
     [1, 2],
     [2, 3],
     [3, 4],
     [0],
     [1],
     [2],
     [3],
     [4]]
    

    对于字符串,它会产生:

    >>> L = ['Explain', 'it', 'to', 'me', 'please']
    >>> result = [L[i:j] for i in xrange(len(L)) for j in xrange(i + 1, len(L) + 1)]
    >>> result.sort(key=lambda x: (-len(x), x))
    >>> pprint.pprint(result)
    [['Explain', 'it', 'to', 'me', 'please'],
     ['Explain', 'it', 'to', 'me'],
     ['it', 'to', 'me', 'please'],
     ['Explain', 'it', 'to'],
     ['it', 'to', 'me'],
     ['to', 'me', 'please'],
     ['Explain', 'it'],
     ['it', 'to'],
     ['me', 'please'],
     ['to', 'me'],
     ['Explain'],
     ['it'],
     ['me'],
     ['please'],
     ['to']]
    

    【讨论】:

    • 我认为key=lambda x: -len(x) 就足够了
    【解决方案2】:

    这是使用来自 itertools 的旧 window 配方的一种方法

    from itertools import islice
    
    def window(seq, n=2):
        "Returns a sliding window (of width n) over data from the iterable"
        "   s -> (s0,s1,...s[n-1]), (s1,s2,...,sn), ...                   "
        it = iter(seq)
        result = tuple(islice(it, n))
        if len(result) == n:
            yield result    
        for elem in it:
            result = result[1:] + (elem,)
            yield result
    
    def all_windows(seq):
        for l in xrange(1, len(seq) + 1):
            for w in window(seq, l):
                yield w
    

    【讨论】:

    • 你可以reduce(list.__add__, all_windows(seq), [])
    • 更改为扁平化结果
    • 我们甚至不需要reduce和使用双下划线的方法,只需list(all_windows(seq))
    • 当前版本不需要
    【解决方案3】:

    很像 cpburnz 的答案,这是通过嵌套列表理解来实现的。
    不同的是,列表是按长度从大到小排序的。

    [L[j:i+j] for i in xrange(len(L), 0, -1) for j in xrange(len(L) - i + 1)]
    

    但是,如果您只需要生成列表,那么请考虑使用生成器编写更易读的代码:

    def all_windows(L):
        for i in xrange(len(L), 0, -1):
            for j in xrange(len(L) - i + 1):
                yield L[j:i+j]
    

    与上面相同的代码,但设计用于迭代:

    for sublist in all_windows(L):
        # does something with sublist
    

    【讨论】:

      猜你喜欢
      • 2020-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多