【问题标题】:Merge list items based on condition within the list根据列表中的条件合并列表项
【发布时间】:2014-03-07 05:21:03
【问题描述】:

我有一个项目清单: 例如:

a = ['IP 123 84', 'apple', 'mercury', 'IP 543 65', 'killer', 'parser', 'goat',
     'IP 549 54 pineapple', 'django', 'python']

我想根据条件合并列表项,即合并所有项,直到以 IP 开头的项。 我想要的输出是:

a = ['IP 123 84 apple mercury', 'IP 543 65 killer parser goat',
     'IP 549 54 pineapple django python']

请建议如何做到这一点。

【问题讨论】:

    标签: python list python-2.7 merge


    【解决方案1】:

    一种有趣的方式:

    import itertools
    
    def predicate_grouper(li, predicate='IP'):
        indices = [i for i,x in enumerate(li) if x.startswith(predicate)]
        slices = [slice(*x) for x in itertools.zip_longest(indices,indices[1:])]
        for sli in slices:
            yield ' '.join(li[sli])
    

    演示:

    list(predicate_grouper(a))
    Out[61]: 
    ['IP 123 84 apple mercury',
     'IP 543 65 killer parser goat',
     'IP 549 54 pineapple django python']
    

    【讨论】:

    • 正是我需要的。我正在使用 Python 2.7 而不是 itertools.zip_longest() 我需要使用 itertools.izip_longest()
    • 我认为上例中的 enumerate(a) 应该是 enumerate(li)
    【解决方案2】:
    import re    
    def group_IP_list(lst):
        groups = []
        word_group = []
        for list_item in lst:
            if re.search(r'^IP',list_item) and word_group:
                groups.append(' '.join(word_group)) 
            elif re.search(r'^IP',list_item):
                word_group = [list_item]
            else: 
                word_group.extend([list_item])
        groups.append(' '.join(word_group)) 
        return groups
    
    #Usage: 
    a = ['IP 123 84','apple','mercury','IP 543 65','killer','parser','goat','IP 549 54   pineapple','django','python']
    print group_IP_list(a)
    #Result:
    ['IP 123 84 apple mercury', 'IP 123 84 apple mercury killer parser goat', 'IP 123 84 apple mercury killer parser goat django python']
    

    【讨论】:

    • 如果“IP”在某些 a 元素中的某处怎么办?
    • 已经算了。我正在使用正则表达式来搜索字符串的开头 (re.search('^IP')。插入符号 (^) 只会匹配字符串的开头;其他任何内容都不会匹配
    【解决方案3】:

    如果字符串'IP'只存在于a的某些元素的头部,则加入列表然后拆分:

    In [99]: ['IP'+i for i in ''.join(a).split('IP')[1:]]
    Out[99]: 
    ['IP 123 84applemercury',
     'IP 543 65killerparsergoat',
     'IP 549 54 pineappledjangopython']
    

    如果a是这样的

    a = ['IP 123 84', 'apple', 'mercury', 'IP 543 65', 'killer', 'parserIP', 'goat',
         'IP 549 54 pineapple', 'django', 'python']                    ^^^^
    

    前一种方法不行,你可以在a中插入一些特殊的序列(不应该出现在a中),然后加入拆分:

    In [11]: for i, v in enumerate(a):
        ...:     if v.startswith('IP'):
        ...:         a[i]='$$$'+v
        ...: ''.join(a).split('$$$')[1:]
    Out[11]: 
    ['IP 123 84applemercury',
     'IP 543 65killerparsergoat',
     'IP 549 54 pineappledjangopython']
    

    【讨论】:

    • 如果'IP' 位于某些a 元素内部怎么办?
    • 如果 'IP' 作为子字符串存在,这将失败。加入列表项,直到该行以 IP 为星标。
    【解决方案4】:

    使用生成器。

    def merge(x, key='IP'):
        tmp = []
        for i in x:
            if (i[0:len(key)] == key) and len(tmp):
                yield ' '.join(tmp)
                tmp = []
            tmp.append(i)
        if len(tmp):
            yield ' '.join(tmp)
    
    a = ['IP 123 84','apple','mercury','IP 543 65','killer','parser','goat','IP 549 54 pineapple','django','python']
    print list(merge(a))
    
    ['IP 123 84 apple mercury', 'IP 543 65 killer parser goat', 'IP 549 54 pineapple django python']
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-26
      • 1970-01-01
      • 2012-07-10
      • 1970-01-01
      • 2019-05-28
      • 1970-01-01
      • 2022-12-23
      相关资源
      最近更新 更多