【问题标题】:Split List By Value and Keep Separators按值拆分列表并保留分隔符
【发布时间】:2017-12-24 16:27:52
【问题描述】:

我有一个名为 list_of_strings 的列表,如下所示:

['a', 'b', 'c', 'a', 'd', 'c', 'e']

我想按一个值(在本例中为 c)拆分此列表。我还想在结果拆分中保留c

所以预期的结果是:

[['a', 'b', 'c'], ['a', 'd', 'c'], ['e']]]

有什么简单的方法吗?

【问题讨论】:

标签: python


【解决方案1】:

这个呢。它应该只对输入进行一次迭代,其中一些在 index 方法中,该方法作为本机代码执行。

def splitkeep(v, c):

    curr = 0
    try:
        nex = v.index(c)
        while True:
            yield v[curr: (nex + 1)]
            curr = nex + 1
            nex += v[curr:].index(c) + 1

    except ValueError:
        if v[curr:]: yield v[curr:]

print(list(splitkeep( ['a', 'b', 'c', 'a', 'd', 'c', 'e'], 'c')))

结果

[['a', 'b', 'c'], ['a', 'd', 'c'], ['e']]

如果最终值是您要拆分的值,我不确定您是否想在结果末尾保留一个空列表。我做了一个你不会做的假设,所以我设置了一个条件,如果它是空的,则排除最终值。

这会导致输入[] 仅导致[],而可以说它可能会导致[[]]

【讨论】:

    【解决方案2】:
    stuff = ['a', 'b', 'c', 'a', 'd', 'c', 'e']
    

    您可以像这样使用'c' 找出索引,然后添加 1,因为您将在它之后拆分,而不是在其索引处:

    indices = [i + 1 for i, x in enumerate(stuff) if x == 'c']
    

    然后像这样提取切片:

    split_stuff = [stuff[i:j] for i, j in zip([0] + indices, indices + [None])]
    

    zip 为您提供类似于(indices[i], indices[i + 1]) 的元组列表,连接的[0] 允许您提取第一部分,[None] 提取最后一个切片 (stuff[i:])

    【讨论】:

    • 请为您的回答提供一些上下文和解释。单独的代码并不能提供很好的答案。
    • 我明白 - 我添加了解释。
    【解决方案3】:

    你可以试试下面的sn-p。使用 more_itertools

    >>> l = ['a', 'b', 'c', 'a', 'd', 'c', 'e']
    >>> from more_itertools import sliced
    >>> list(sliced(l,l.index('c')+1))
    

    输出是:

    [['a', 'b', 'c'], ['a', 'd', 'c'], ['e']]
    

    【讨论】:

      【解决方案4】:

      您可以使用more_itertoools 简单明了地完成此操作:

      from more_itertools import split_after
      
      
      lst = ["a", "b", "c", "a", "d", "c", "e"]
      list(split_after(lst, lambda x: x == "c"))
      # [['a', 'b', 'c'], ['a', 'd', 'c'], ['e']]
      

      另一个例子,这里我们通过简单地更改predicate来拆分单词:

      lst = ["ant", "bat", "cat", "asp", "dog", "carp", "eel"]
      list(split_after(lst, lambda x: x.startswith("c")))
      # [['ant', 'bat', 'cat'], ['asp', 'dog', 'carp'], ['eel']]
      

      【讨论】:

      • 这仅适用于我的示例的特殊情况。它不会对值c 进行拆分,而是对列表进行平均分块。
      • @ScientiaEtVeritas 我现在看到了您的要求。此答案已使用同一个库修复。
      • 您不应该使用is 来比较字符串。
      • 感谢您的反馈。
      【解决方案5】:
      list_of_strings = ['a', 'b', 'c', 'a', 'd', 'c', 'e']
      
      value = 'c'
      new_list = []
      temp_list = []
      for item in list_of_strings:
          if item is value:
              temp_list.append(item)
              new_list.append(temp_list[:])
              temp_list.clear()
          else:
              temp_list.append(item)
      
      if (temp_list):
          new_list.append(temp_list)
      
      print(new_list)
      

      【讨论】:

        【解决方案6】:
        def spliter(value, array):
            res = []
            while value in array:
                index = array.index(value)
                res.append(array[:index + 1])
                array = array[index + 1:]
            if array:
                # Append last elements
                res.append(array)
            return res
        
        a = ['a', 'b', 'c', 'a', 'd', 'c', 'e']
        print(spliter('b',a))
        # [['a', 'b'], ['c', 'a', 'd', 'c', 'e']]
        print(spliter('c',a))
        # [['a', 'b', 'c'], ['a', 'd', 'c'], ['e']]
        

        【讨论】:

        • 现在看起来好多了。你一定编辑了一些东西。不记得了。反正我没有DV
        • 谢谢 :) 尝试此解决方案后似乎有点慢,但它按预期工作。
        • 会很慢。 value in array 位本质上使其成为二次时间。相反,您可以在逐渐变小的切片上调用数组,然后将其设为线性。
        • @PaulRooney 是的,您可以使用try except else 改进这部分代码,就像这里有人描述的stackoverflow.com/questions/7571635/… 但有必要吗?
        • 在我的数据集上,此代码需要 5 分钟,而批准的答案需要 2 秒。
        【解决方案7】:

        这个相当好玩的脚本怎么样:

        a = ['a', 'b', 'c', 'a', 'd', 'c', 'e']
        
        b = ''.join(a).split('c')  # ['ab', 'ad', 'e']
        
        c = [x + 'c' if i < len(b)-1 else x for i, x in enumerate(b)]  # ['abc', 'adc', 'e']
        
        d = [list(x) for x in c if x]
        print(d)  # [['a', 'b', 'c'], ['a', 'd', 'c'], ['e']]
        

        它还可以处理带有"c"的开头和结尾

        a = ['c', 'a', 'b', 'c', 'a', 'd', 'c', 'e', 'c']
        d -> [['c'], ['a', 'b', 'c'], ['a', 'd', 'c'], ['e', 'c']]
        

        【讨论】:

        • 谢谢 :) 这个解决方案的问题是,由于加入了字符串,这只适用于字符而不是一般的字符串。
        • 你能提供一个导致它失败的例子吗?
        • ['a', 'cb', 'c', 'ca', 'aad', 'c', 'ccc', 'e'],这是我的意思的一个例子。
        【解决方案8】:

        您可以尝试以下方法:

        list_of_strings = ['a', 'b', 'c', 'a', 'd', 'c', 'e']
        
        output = [[]]
        
        for x in list_of_strings:
            output[-1].append(x)
            if x == 'c':
                output.append([])
        

        虽然应该注意,如果您输入的最后一个元素是'c',这将在您的输出中附加一个空列表

        【讨论】:

        • 只需使用标志移动 for 正文顶部的空列表的附加部分。我刚刚发布了similar answer 类似的问题。
        猜你喜欢
        • 1970-01-01
        • 2019-05-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-10-11
        • 2016-11-26
        • 2022-11-03
        相关资源
        最近更新 更多