【问题标题】:Python: Get all combinations of sequential elements of listPython:获取列表顺序元素的所有组合
【发布时间】:2015-10-01 08:40:45
【问题描述】:

给定一个数组说x = ['A','I','R'] 我希望输出为

[['A','I','R'],['A','I'],['I','R'],['A'],['I'],['R']]

我不想要输出的是:

[['A','I','R'],['A','I'],['I','R'],['A','R'],['A'],['I'],['R']]  # extra ['A','R'] which is not in sequence .

下面是给出我不想要的输出的代码:

letter_list = [a for a in str]
all_word = []
for i in xrange(0,len(letter_list)):
    all_word = all_word + (map(list, itertools.combinations(letter_list,i))) # dont use append. gives wrong result.
all_word = filter(None,all_word) # remove empty combination
all_word = all_word + [letter_list] # add original list

我的意思是我只想要序列的组合。有什么方法可以使用itertools 还是我应该编写自定义函数?

【问题讨论】:

  • 此处可能存在重复:Substrings of a string
  • 请注意在 Code Review SE 的 my answer 到您的 follow up question 中解释的指数内存使用情况。对于长度为 1000 个字符的文本,这样拆分时需要 167167000 个字符,内存占用为 1.25GB。

标签: python itertools


【解决方案1】:

是的,你可以使用itertools

>>> x = ['A', 'I', 'R']
>>> xs = [x[i:j] for i, j in itertools.combinations(range(len(x)+1), 2)]
>>> xs
[['A'], ['A', 'I'], ['A', 'I', 'R'], ['I'], ['I', 'R'], ['R']]
>>> sorted(xs, key=len, reverse=True)
[['A', 'I', 'R'], ['A', 'I'], ['I', 'R'], ['A'], ['I'], ['R']]

信用:answer by hochl

【讨论】:

    【解决方案2】:

    尝试使用yield:

    x = ['A','I','R']
    
    def groupme(x):
        s = tuple(x)
        for size in range(1, len(s) + 1):
            for index in range(len(s) + 1 - size):
                yield list(x[index:index + size])
    
    list(groupme(x))
    
    >>> [['A'], ['I'], ['R'], ['A', 'I'], ['I', 'R'], ['A', 'I', 'R']]
    

    【讨论】:

    • 在当前的解决方案中,这是唯一一个不使用大量内存的解决方案,因为它使用 yield 只在迭代时给你想要的单词。但是,它仍然会为使用 1000 个字符的测试用例生成 500500 个不同的元素。 :-D
    【解决方案3】:

    不要试图这么神奇:两个循环会做你想做的事;一个超过可能的序列开始,内部超过可能的序列长度:

    x = "AIR" # strings are iterables/sequences, too!
    all_words = []
    for begin in xrange(len(x)):
        for length in xrange(1,len(x) - begin+1):
            all_words.append(x[begin:begin+length])
    

    【讨论】:

    • 如上面评论中所述,当文本输入包含超过几百个字符时,这确实是内存密集型的。
    【解决方案4】:

    使用列表理解:

    letters=['A', 'I', 'R']
    [letters[start:end+1] 
     for start in xrange(len(letters)) 
     for end in xrange(start, len(letters))]
    
    [['A'], ['A', 'I'], ['A', 'I', 'R'], ['I'], ['I', 'R'], ['R']]
    

    如果您提出的顺序很重要(从最长到最短,并且起始位置的长度相同),您可以改为:

    [letters[start:start+l+1]
     for l in range(len(letters))[::-1]
     for start in xrange(len(letters)-l)]
    
    [['A', 'I', 'R'], ['A', 'I'], ['I', 'R'], ['A'], ['I'], ['R']]
    

    只是为了解决 Holroy 的评论。如果不使用列表解析,而是使用生成器表达式(只需用 () 替换外部 []),那么需要代码的内存就会少得多。但是在这种情况下,您必须小心不要多次使用结果,或者例如不要尝试对结果使用列表方法(例如 len 或删除元素)。

    【讨论】:

    • 如上面评论中所述,当文本输入包含超过几百个字符时,这确实是内存密集型的。
    猜你喜欢
    • 2017-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-14
    • 1970-01-01
    • 2019-04-08
    • 1970-01-01
    相关资源
    最近更新 更多