【问题标题】:Concatenate elements from a list based on a criteria根据条件连接列表中的元素
【发布时间】:2021-01-17 22:47:23
【问题描述】:

假设我们有列表

L = ['a', '!b', '!c', 'd', 'e', '!f', 'g', 'h']

如果它以! 开头,我们希望将每个元素与前一个元素连接起来。

预期输出:

M = ['a!b!c', 'd', 'e!f', 'g', 'h']

这可行,但将join 列表转换为字符串,然后将字符串重新拆分为列表可能不必要地复杂:

M = ''.join(('' if l.startswith('!') else '\n') + l for l in L).splitlines()[1:]
# ['a!b!c', 'd', 'e!f', 'g', 'h']

有没有更简单的方法可以根据条件 ('!' in l) 连接列表中的元素?

【问题讨论】:

    标签: python list concatenation


    【解决方案1】:

    您可能正在寻找单线,但是这个不太复杂的循环怎么样?

    L = ['a', '!b', '!c', 'd', 'e', '!f', 'g', 'h']
    M = []
    for x in L:
        if x.startswith("!"):
            M[-1] += x
        else:
            M.append(x)
    # ['a!b!c', 'd', 'e!f', 'g', 'h']
    

    如果你喜欢简短而不是可读,你可以使用三元组pop...

    for x in L:
        M.append(M.pop() + x if x.startswith("!") else x)
    

    我对@9​​87654324@、groupbytakewhile 或“加入和拆分”解决方案(如您所拥有的解决方案)的“聪明”单线解决方案进行了更多思考,但如果它们适用于他们只是让它变得更复杂。我认为这是其中一种情况,如果你想要一个单行,你应该为它定义一个函数。

    【讨论】:

    • 确实不错,这是没有列表理解的更经典的方式。最好,如果可能的话,我会对一个班轮感兴趣:)
    • 我也感觉这样的groupby应该是可能的,但棘手的部分是你必须加入组之间的“边界”(至少如果你使用.startswith('!') 作为密钥)
    • 如果我可以建议对第二个进行微小的编辑,这样如果第一个元素以 ! 开头就不会中断:M.append(M.pop() + x if M and x.startswith("!") else x)
    • 我正在尝试使用groupby,但它变得非常讨厌。我认为显式 for 循环更能实现这一目标
    • 我本来打算发布类似的东西,但你抢先了。同样,我查看了groupbyreduce,但复杂性远远超过单线能力。我能想到的最好的办法是改编 OP 的原始(加入/拆分)想法,但我真的认为简单的 for 循环(如果需要,包含在函数中)是最好的解决方案。你有我的投票...
    【解决方案2】:

    作为连接和拆分单行的稍微紧凑的版本,如果您的元素是单个字符(或可与明确定义的正则表达式匹配的内容),您可以连接成一个字符串,然后使用 re.findall 进行匹配里面有!的部分:

    import re
    
    L = ['a', '!b', '!c', 'd', 'e', '!f', 'g', 'h']
    print(re.findall('([a-z](?:![a-z])*)', ''.join(L)))
    

    输出

    ['a!b!c', 'd', 'e!f', 'g', 'h']
    

    如果您的列表实际上包含比单个字符更复杂的元素,您可以将正则表达式(两个位置)中的 [a-z] 替换为与这些元素匹配的正则表达式。

    【讨论】:

    • 不错的解决方案!但是 L 的每个元素都可以有多个字符和!在他们里面。条件只是“开始于!”。
    • @Basj 你能提供一些示例数据吗?我不认为值中的! 是一个问题,因为这些值将继续加入findall。可能就像将[a-z] 更改为[a-z]+ 一样简单。
    【解决方案3】:

    您可以加入元素,然后删除“!”之前的分隔符并再次拆分:

    L = ['a', '!b', '!c', 'd', 'e', '!f', 'g', 'h']
    
    M = ",".join(L).replace(",!","!").split(",")
    
    print(M)
    
    # ['a!b!c', 'd', 'e!f', 'g', 'h']
    

    【讨论】:

    • 确实不错的解决方案!
    猜你喜欢
    • 1970-01-01
    • 2011-11-29
    • 2018-10-12
    • 1970-01-01
    • 1970-01-01
    • 2017-08-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多