【问题标题】:Python - How to join elements in a list that are separated by a certain valuePython - 如何连接列表中由某个值分隔的元素
【发布时间】:2015-06-05 20:07:57
【问题描述】:

假设我有一个如下所示的列表:

['1', '+', '2', '+', '3', 'C', '4', 'C', '5', '-', '6', '+', '7', 'C', '8']

我想修改它,使由'C' 分隔的所有元素连接在一起。结果应如下所示:

['1', '+', '2', '+', '345', '-', '6', '+', '78']

我一直在尝试迭代地执行此操作,但问题是每当我删除一个元素时,列表的大小就会发生变化,并且迭代会越界。任何指针表示赞赏。谢谢!

【问题讨论】:

  • 不要删除任何东西;在您浏览数据时构建一个新列表。
  • 我很好奇你是如何获得这样一个……有趣的数据结构的。
  • @alexis 哇,我不知道在过去的一个小时里我是怎么想到的......我一定是在兔子洞里走得太远了,所有的逻辑都离开了我跨度>
  • @TigerhawkT3 blog.svpino.com/2015/05/07/… 问题编号 5。

标签: python list iteration


【解决方案1】:

过滤掉“C”,然后对连续的数字进行分组:

from itertools import groupby

data = ['1', '+', '2', '+', '3', 'C', '4', 'C', '5', '-', '6', '+', '7', 'C', '8']
new_data = [''.join(g) if k else next(g) for k, g in groupby((el for el in data if el != 'C'), key=str.isdigit)]
# ['1', '+', '2', '+', '345', '-', '6', '+', '78']

【讨论】:

  • 这假设只有数字要连接。
  • @Martijn 确实......但根据问题#5,OP 已作为评论发布 - 似乎只有数字在使用......(不太确定 C 来自哪里虽然...)
  • 可能他们通过在数字之间尝试'+''-''C'(用于连接)中的每一个来强制解决方案。
  • @MartijnPieters 是的,这正是我正在做的。出于好奇,我想用一种艰难而愚蠢的方法来测试它,看看它的性能有多差,然后将它与更好的算法进行比较。
【解决方案2】:

您可以使用生成器函数,该函数仅在下一个值不是C 时生成值,否则累积:

def join_by(it, sep):
    it = iter(it)
    prev = next(it)
    for elem in it:
        if elem == sep:
            prev += next(it)
        else:
            yield prev
            prev = elem
    yield prev

演示;这不仅限于数字,也不限于特定的分隔符:

>>> orig = ['1', '+', '2', '+', '3', 'C', '4', 'C', '5', '-', '6', '+', '7', 'C', '8']
>>> list(join_by(orig, 'C'))
['1', '+', '2', '+', '345', '-', '6', '+', '78']
>>> list(join_by(['foo', '-', 'bar', 'baz'], '-'))
['foobar', 'baz']

要解决难题,您可以在此处作弊并使用eval()

>>> import operator
>>> from itertools import product
>>> digits = '123456789'
>>> ops = (' - ', ' + ', '')
>>> for combo in product(ops, repeat=len(digits) - 1):
...     expr = zip(digits, combo + ('',))
...     expr = ''.join([c for digit_oper in expr for c in digit_oper])
...     result = eval(expr)
...     if result == 100:
...         print(expr)
... 
1 + 2 + 3 - 4 + 5 + 6 + 78 + 9
1 + 2 + 34 - 5 + 67 - 8 + 9
1 + 23 - 4 + 5 + 6 + 78 - 9
1 + 23 - 4 + 56 + 7 + 8 + 9
12 - 3 - 4 + 5 - 6 + 7 + 89
12 + 3 - 4 + 5 + 67 + 8 + 9
12 + 3 + 4 + 5 - 6 - 7 + 89
123 - 4 - 5 - 6 - 7 + 8 - 9
123 - 45 - 67 + 89
123 + 4 - 5 + 67 - 89
123 + 45 - 67 + 8 - 9

【讨论】:

    【解决方案3】:
    lst = ['1', '+', '2', '+', '3', 'C', '4', 'C', '5', '-', '6', '+', '7', 'C', '8']
    newlist = [lst[0]]
    for idx, item in enumerate(lst[1:]):
        if item == 'C':
            continue # do nothing if it's a C
        if lst[idx] == 'C':
            newlist[-1] += item # add it to the last item if it follows a C
        else:
            newlist.append(item) # add it to the list
    

    结果:

    ['1', '+', '2', '+', '345', '-', '6', '+', '78']
    

    【讨论】:

      【解决方案4】:

      此代码适用于任何给定的列表和值。

      old_list = ['1', '+', '2', '+', '3', 'C', '4', 'C', '5', '-', '6', '+', '7', 'C', '8']
      new_list = []
      for index, val in enumerate(old_list):
          if val == 'C':
              new_list[-1] += old_list[index+1]
          elif old_list[index-1] != 'C':
              new_list.append(val)
      

      【讨论】:

      • x 来自哪里?
      • NameError: name 'x' is not defined
      • 想要让代码更具可读性却忘了把x改成val :)
      【解决方案5】:
      import ast
      
      L=['1', '+', '2', '+', '3', 'C', '4', 'C', '5', '-', '6', '+', '7', 'C', '8']
      
      s=str(L).replace(", 'C', ", "")
      
      out=ast.literal_eval(s)
      
      print out
      

      输出:

      ['1', '+', '2', '+', '345', '-', '6', '+', '78']
      

      【讨论】:

        【解决方案6】:

        不需要列表理解,只需找到您的分隔符并将其余部分连接起来

        a = ['1', '+', '2', '+', '3', 'C', '4', 'C', '5', '-', '6', '+', '7', 'C', '8']
        firstIndex = a.index('C')
        revertedLastIndex = a[::-1].index('C') # index in reverted list 
        lastIndex = len(a) - 1 - revertedLastIndex  # -1 for 0-indexed lists
        

        所以我们现在可以加入firstIndexlastIndex 之间的列表部分,然后将其余部分连接起来

        newList = a[:firstIndex] + ["".join(a[firstIndex:lastIndex])] + a[lastIndex:]
        

        编辑:“不需要列表理解”我的意思是当然不需要 显式 迭代,index 函数在内部完成

        【讨论】:

        • TypeError: can only concatenate list (not "str") to list
        • 详情! =p 先将字符串转换成列表。编辑答案
        【解决方案7】:

        Python 的奇特功能非常好,因为它们使代码的逻辑非常非常容易理解。如果他们不这样做,我更愿意保持简单和可验证:

        stuff = ['1', '+', '2', '+', '3', 'C', '4', 'C', '5', '-', '6', '+', '7', 'C', '8']
        concat = False
        newstuff = []
        for a in stuff:
            if concat:
                newstuff[-1] += a
                concat = False
            elif a == "C":
                concat = True
            else:
                newstuff.append(a)
        

        【讨论】:

          猜你喜欢
          • 2020-08-01
          • 2020-08-22
          • 2013-01-28
          • 2011-08-18
          • 1970-01-01
          • 2013-11-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多