代码之家  ›  专栏  ›  技术社区  ›  Jani

如何基于分隔符将列表拆分为子列表,类似于str.split()?

  •  4
  • Jani  · 技术社区  · 7 年前

    给出如下列表:

    [a, SEP, b, c, SEP, SEP, d]
    

    如何将其拆分为子列表:

    [[a], [b, c], [], [d]]
    

    实际上,我需要一个相当于 str.split() 用于列表。我能拼凑出一些东西,但我似乎不能想出任何整洁和/或蟒蛇式的东西。

    我从迭代器中获取输入,因此处理迭代器的生成器也是可以接受的。

    更多示例:

    [a, SEP, SEP, SEP] -> [[a], [], [], []]
    
    [a, b, c] -> [[a, b, c]]
    
    [SEP] -> [[], []]
    
    7 回复  |  直到 7 年前
        1
  •  12
  •   wim    5 年前

    一个简单的生成器适用于您问题中的所有情况:

    def split(sequence, sep):
        chunk = []
        for val in sequence:
            if val == sep:
                yield chunk
                chunk = []
            else:
                chunk.append(val)
        yield chunk
    
        2
  •  2
  •   Matthew Page    7 年前

    我的第一个Python程序:)

    from pprint import pprint
    my_array = ["a", "SEP", "SEP", "SEP"]
    my_temp = []
    my_final = []
    for item in my_array:
      if item != "SEP":
        my_temp.append(item)
      else:
        my_final.append(my_temp);
        my_temp = []
    pprint(my_final);
    
        3
  •  0
  •   pault Tanjin    7 年前

    我不确定是否有一个简单的答案 itertools.groupby 解决方案,但这里有一个迭代方法应该可以工作:

    def mySplit(iterable, sep):
        output = []
        sepcount = 0
        current_output = []
        for i, elem in enumerate(iterable):
            if elem != sep:
                sepcount = 0
                current_output.append(elem)
                if (i==(len(iterable)-1)):
                    output.append(current_output)
            else:
                if current_output: 
                    output.append(current_output)
                    current_output = []
    
                sepcount+=1
    
                if (i==0) or (sepcount > 1):
                    output.append([])
                if (i==(len(iterable)-1)):
                    output.append([])
    
        return output
    

    测试您的示例:

    testLists = [
        ['a', 'SEP', 'b', 'c', 'SEP', 'SEP', 'd'],
        ["a", "SEP", "SEP", "SEP"],
        ["SEP"],
        ["a", "b", "c"]
    ]
    
    for tl in testLists:
        print(mySplit(tl, sep="SEP"))
    #[['a'], ['b', 'c'], [], ['d']]
    #[['a'], [], [], []]
    #[[], []]
    #[['a', 'b', 'c']]
    

    str.split(sep) :

    for tl in testLists:
        print("".join(tl).split("SEP"))
    #['a', 'bc', '', 'd']
    #['a', '', '', '']
    #['', '']
    #['abc']
    

    for tl in testLists:
        print([list(x) for x in "".join(tl).split("SEP")])
    #[['a'], ['b', 'c'], [], ['d']]
    #[['a'], [], [], []]
    #[[], []]
    #[['a', 'b', 'c']]
    

    但是 mySplit() 函数更一般。

        4
  •  0
  •   a_guest    7 年前

    对于 list tuple 对象您可以使用以下各项:

    def split(seq, sep):
        start, stop = 0, -1
        while start < len(seq):
            try:
                stop = seq.index(sep, start)
            except ValueError:
                yield seq[start:]
                break
            yield seq[start:stop]
            start = stop + 1
        else:
            if stop == len(seq) - 1:
                yield []
    

    我不会用发电机,但它很快。

        5
  •  0
  •   a_guest    7 年前

    你可以用 itertools.takewhile :

    def split(seq, sep):
        seq, peek = iter(seq), sep
        while True:
            try:
                peek = next(seq)
            except StopIteration:
                break
            yield list(it.takewhile(sep.__ne__, it.chain((peek,), seq)))
        if peek == sep:
            yield []
    

    这个 it.chain seq 他筋疲力尽了。注意,如果需要,使用这种方法很容易生成生成器而不是列表。

        6
  •  -1
  •   Samuel Nde    7 年前

    l = ['a', 'SEP', 'b', 'c', 'SEP', 'SEP', 'd']
    
    def sublist_with_words(word, search_list):
        res = []
        for i in range(search_list.count(word)):
            index = search_list.index(word)
            res.append(search_list[:index])
            search_list = search_list[index+1:]
        res.append(search_list)
        return res
    

    当我尝试您提供的案例时:

    print(sublist_with_words(word = 'SEP', search_list=l))
    print(sublist_with_words(word = 'SEP', search_list=['a', 'b', 'c']))
    print(sublist_with_words(word = 'SEP', search_list=['SEP']))
    

    输出为:

    [['a'], ['b', 'c'], [], ['d']]
    [['a', 'b', 'c']]
    [[], []]
    
        7
  •  -1
  •   maciek    5 年前

    itertools.takewhile @客人的方法简化了:

    def split(seq, sep):
        from itertools import takewhile
        iterator = iter(seq)
        while subseq := list(takewhile(lambda x: x != sep, iterator)):
            yield subseq
    

    请注意,它在第一个空子序列返回。

        8
  •  -3
  •   yang5    7 年前

    import re
    
    def split_list(nums, n):
        nums_str = str(nums)
        splits = nums_str.split(f"{n},")
    
        patc = re.compile(r"\d+")
        group = []
        for part in splits:
            group.append([int(v) for v in patc.findall(part)])
    
        return group
    
    if __name__ == "__main__":
        l = [1, 2, 3, 4, 3, 6, 7, 3, 8, 9, 10]
        n = 3
        split_l = split_list(l, n)
        assert split_l == [[1, 2], [4], [6, 7], [8, 9, 10]]