【问题标题】:Splitting a list of strings based on specific words根据特定单词拆分字符串列表
【发布时间】:2021-02-13 02:20:21
【问题描述】:

我有一个包含特定文件路径的列表,例如

path_list =['Animals/dog_00238/2D_rendering/131/view/full/0',
          'Animals/dog_00238/2D_rendering/131/view/full/1',
          'Animals/dog_00238/2D_rendering/131/view/full/2',
          'Animals/dog_00238/2D_rendering/906271/view/full/1',
          'Animals/dog_00239/2D_rendering/906271/view/full/2',
          'Animals/dog_00239/2D_rendering/965947/view/full/0',
          'Animals/dog_00239/2D_rendering/965947/view/full/1',
          'Animals/dog_00239/2D_rendering/965947/view/full/2',<------ Last time dog_00239 appears #first break point
          'Animals/dog_00240/2D_rendering/965947/view/full/3',
          'Animals/dog_00240/2D_rendering/982160/view/full/0',
          'Animals/dog_00240/2D_rendering/982160/view/full/1',
          'Animals/dog_00241/2D_rendering/982160/view/full/2',
          'Animals/dog_00241/2D_rendering/141/view/full/0',
          'Animals/dog_00241/2D_rendering/141/view/full/1',<------ Last time dog_00241 appears #Second breakpoint
          'Animals/dog_00242/2D_rendering/1881/view/full/3',
          'Animals/dog_00242/2D_rendering/1881/view/full/4',
          'Animals/dog_00242/2D_rendering/2487/view/full/0',
          'Animals/dog_00242/2D_rendering/2487/view/full/1',]

我想做的是将此列表拆分为 3 个新的较小列表。

第一个列表将从开始到第一个断点

Fisrt_list = ['Animals/dog_00238/2D_rendering/131/view/full/0',
         'Animals/dog_00238/2D_rendering/131/view/full/1',
         'Animals/dog_00238/2D_rendering/131/view/full/2',
         'Animals/dog_00238/2D_rendering/906271/view/full/1',
         'Animals/dog_00239/2D_rendering/906271/view/full/2',
         'Animals/dog_00239/2D_rendering/965947/view/full/0',
         'Animals/dog_00239/2D_rendering/965947/view/full/1',
         'Animals/dog_00239/2D_rendering/965947/view/full/2',]<------ Last time dog_00239 appears #first break point

第二个列表将在第一个断点之后直到第二个断点

second_list = ['Animals/dog_00240/2D_rendering/965947/view/full/3',
     'Animals/dog_00240/2D_rendering/982160/view/full/0',
     'Animals/dog_00240/2D_rendering/982160/view/full/1',
     'Animals/dog_00241/2D_rendering/982160/view/full/2',
     'Animals/dog_00241/2D_rendering/141/view/full/0',
     'Animals/dog_00241/2D_rendering/141/view/full/1',]<------ Last time dog_00241 appears #Second breakpoint

第三个列表将在第二个断点之后直到结束

third_list = ['Animals/dog_00242/2D_rendering/1881/view/full/3',
     'Animals/dog_00242/2D_rendering/1881/view/full/4',
     'Animals/dog_00242/2D_rendering/2487/view/full/0',
     'Animals/dog_00242/2D_rendering/2487/view/full/1',]

到目前为止,我尝试的是,我创建了一个 for 循环,并在满足 if 条件时将其中断,然后查看我得到的结果,例如:

new_paths = []
fisrt_breakpoint = 'dog_00239'

for i in range (len(path_list)):
new_paths.append(path_list[i])
   if fisrt_breakpoint in path_list:
    break

这确实拆分了列表并保留了其中的一小部分,但它保留在 new_paths 中的是我设置的断点之后的元素,而不是该断点之前的元素。但我也无处设置条件,因为我不知道该怎么做,在这个词最后一次出现在这个列表中时用作断点,因为我假设即使上面的代码有效,它也会拆分它第一次看到“dog_00239”这个词。

我也试过了:

new_paths = [x for x in path_list if first_breakpoint in x]

但这会获取所有包含“dog_00239”的项目,而我想要做的是让所有内容都到此为止。

提前感谢您的宝贵时间, 我真的很感激任何帮助,对于任何错误,或者我对我的问题不是很清楚,因为我是这里和 Python 的新手。

【问题讨论】:

    标签: python list


    【解决方案1】:

    您可以使用itertools.groupby

    import itertools
    import re
    
    # this is the function you define ranges
    def get_breakpoint_id(x):
        if(x <= 239): # i.e. /dog_00239
            return 0
        elif(239 < x <= 241): # i.e. /dog_00240 to /dog_00241
            return 1
        else:
            return 2
    
    
    [list(g) for _,g in itertools.groupby(path_list, key=lambda x: get_breakpoint_id(int(re.findall(r'dog_(\d+)/', x)[0])))]
    
    [['Animals/dog_00238/2D_rendering/131/view/full/0',
      'Animals/dog_00238/2D_rendering/131/view/full/1',
      'Animals/dog_00238/2D_rendering/131/view/full/2',
      'Animals/dog_00238/2D_rendering/906271/view/full/1',
      'Animals/dog_00239/2D_rendering/906271/view/full/2',
      'Animals/dog_00239/2D_rendering/965947/view/full/0',
      'Animals/dog_00239/2D_rendering/965947/view/full/1',
      'Animals/dog_00239/2D_rendering/965947/view/full/2'],
     ['Animals/dog_00240/2D_rendering/965947/view/full/3',
      'Animals/dog_00240/2D_rendering/982160/view/full/0',
      'Animals/dog_00240/2D_rendering/982160/view/full/1',
      'Animals/dog_00241/2D_rendering/982160/view/full/2',
      'Animals/dog_00241/2D_rendering/141/view/full/0',
      'Animals/dog_00241/2D_rendering/141/view/full/1'],
     ['Animals/dog_00242/2D_rendering/1881/view/full/3',
      'Animals/dog_00242/2D_rendering/1881/view/full/4',
      'Animals/dog_00242/2D_rendering/2487/view/full/0',
      'Animals/dog_00242/2D_rendering/2487/view/full/1']]
    

    【讨论】:

    • 刚刚尝试了您的解决方案,它确实按预期工作,但我根本没有使用 itertools.groupby,所以我想问你一些问题。首先,新列表存储在哪里,之后我如何访问它们并对它们执行其他操作?还有在..(int(re.findall(r'dog_(\d+)/', x)[0])))] 在 _(\d+)/' 之后这是如何工作的,直到现在我明白了,但是 ,x ?。再次感谢您
    • 您可以将输出存储在新列表output = [list(g) for _,g in itertools.groupby(path_list, key=lambda x: get_breakpoint_id(int(re.findall(r'dog_(\d+)/', x)[0])))] 中。然后你可以使用output 列表。
    • (int(re.findall(r'dog_(\d+)/', x)[0])))这里其实regular expression是用来提取数字的dog_XXXX。然后根据提取到的XXXX进行分组。
    • 您可以在线阅读有关itertools.groupby() 的更多信息。 Basicall id有一个列表[1,1,1,2,2,1,1,4,4,4]它可以像(1,1,1), (2,2), (1,1), (4,4,4)一样分组它
    【解决方案2】:

    对于不涉及导入包的替代解决方案,您可以使用嵌套的 for 循环:

    breakpoints = ["dog_00240", "dog_00242"] 
    path_list =['Animals/dog_00238/2D_rendering/131/view/full/0',
              'Animals/dog_00238/2D_rendering/131/view/full/1',
              'Animals/dog_00238/2D_rendering/131/view/full/2',
              'Animals/dog_00238/2D_rendering/906271/view/full/1',
              'Animals/dog_00239/2D_rendering/906271/view/full/2',
              'Animals/dog_00239/2D_rendering/965947/view/full/0',
              'Animals/dog_00239/2D_rendering/965947/view/full/1',
              'Animals/dog_00239/2D_rendering/965947/view/full/2',
              'Animals/dog_00240/2D_rendering/965947/view/full/3',
              'Animals/dog_00240/2D_rendering/982160/view/full/0',
              'Animals/dog_00240/2D_rendering/982160/view/full/1',
              'Animals/dog_00241/2D_rendering/982160/view/full/2',
              'Animals/dog_00241/2D_rendering/141/view/full/0',
              'Animals/dog_00241/2D_rendering/141/view/full/1',
              'Animals/dog_00242/2D_rendering/1881/view/full/3',
              'Animals/dog_00242/2D_rendering/1881/view/full/4',
              'Animals/dog_00242/2D_rendering/2487/view/full/0',
              'Animals/dog_00242/2D_rendering/2487/view/full/1',]
    lists = []
    new_list = []
    
    for file_path in path_list:
        for point in breakpoints:
            # If point is a breakpoint, add new_list to lists
            if point in file_path:
                lists.append(new_list)
                new_list = []
                # Remove breakpoint
                breakpoints.remove(point)
                continue
        # Otherwise, add path to new_list
        new_list.append(file_path)
    # Add final new_list to lists
    lists.append(new_list)
            
    first = lists[0]
    second = lists[1]
    third = lists[2]
    
    print(first, second, third)
    # Prints 
    """ (['Animals/dog_00238/2D_rendering/131/view/full/0',  
     'Animals/dog_00238/2D_rendering/131/view/full/1', 
    'Animals/dog_00238/2D_rendering/131/view/full/2', 
    'Animals/dog_00238/2D_rendering/906271/view/full/1', 
    'Animals/dog_00239/2D_rendering/906271/view/full/2', 
    'Animals/dog_00239/2D_rendering/965947/view/full/0', 
    'Animals/dog_00239/2D_rendering/965947/view/full/1', 
    'Animals/dog_00239/2D_rendering/965947/view/full/2'], 
    ['Animals/dog_00240/2D_rendering/965947/view/full/3', 
    'Animals/dog_00240/2D_rendering/982160/view/full/0', 
    'Animals/dog_00240/2D_rendering/982160/view/full/1', 
    'Animals/dog_00241/2D_rendering/982160/view/full/2', 
    'Animals/dog_00241/2D_rendering/141/view/full/0', 
    'Animals/dog_00241/2D_rendering/141/view/full/1'], 
    ['Animals/dog_00242/2D_rendering/1881/view/full/3', 
    'Animals/dog_00242/2D_rendering/1881/view/full/4', 
    'Animals/dog_00242/2D_rendering/2487/view/full/0', 
    'Animals/dog_00242/2D_rendering/2487/view/full/1']) """
    

    请注意,我将断点设置为要中断的第一个路径,而不是到达它的最后一个实例后要中断的路径。

    【讨论】:

    • 刚刚尝试了您提出的解决方案,它确实工作得很好,我的断点是总体起点 (0) 和总体终点 (10000) 的终点,因为我有成千上万条这样的路径,我恐怕在那里可能是跳跃,有时下一个起点可能在数字上不一定是下一个,即。 239 接下来 240 但我可以找到确切的下一个起点并按照您的建议。
    【解决方案3】:

    简单紧凑的解决方案:

    breakpoints_numbers = [0,239,241,999]
    breakpoints_paths = [f'Animals/dog_00{b}' for b in breakpoints_numbers]
    pathslist = [sublist for sublist in [[p for p in path_list if p>b[0] and p<=b[1]] for b in zip(breakpoints_paths[:-1],breakpoints_paths[1:])] if sublist != []]
    

    在第一行创建一个断点列表,包括 000 和 999。

    在第二行中,它们被转换为路径,可用于比较。

    在第三行中,您有您想要的列表列表,这些列表仅在下限进行过滤,并在上限进行过滤,这正是您所期望的。

    【讨论】:

    • 我刚刚尝试了您的解决方案,但您提出的确切示例并给出了结果 [['Animals/dog_00238/2D_rendering/131/view/full/0', 'Animals/dog_00238/2D_rendering/131 /view/full/1'、'Animals/dog_00238/2D_rendering/131/view/full/2'、'Animals/dog_00238/2D_rendering/906271/view/full/1'、'Animals/dog_00239/2D_rendering/906271/view /full/2', 'Animals/dog_00242/2D_rendering/1881/view/full/3', 'Animals/dog_00242/2D_rendering/1881/view/full/4', 'Animals/dog_00242/2D_rendering/2487/view/full /0', 'Animals/dog_00242/2D_rendering/2487/view/full/1'], [], []]
    • 所以它创建了一个包含所有元素的新列表,最后两个为空
    • 你是对的,还有空的子列表。我已经用清理更新了答案以避免它们。该版本正在添加[sublist for sublist in __dirypathslistwithemptysublists__ if sublist != []]
    • 它不仅会删除最后的空文件,还会删除中间的空文件,一旦它们看起来相当不必要 - 至少对我来说,我不知道。
    • 感谢您的更新,但 pathslist = [sublist for sublist in [[p for p in path_list if p&gt;b[0] and p&lt;=b[1]] for b in zip(breakpoints_paths[:-1],breakpoints_paths[1:]) if sublist != []]] 。我认为最后缺少 ] ,除此之外,我认为您的意思是 sublist!= [] 而不是 sublist !+ [] 。但即使进行了这些更改,它也会引发NameError: name 'sublist' is not defined
    猜你喜欢
    • 2021-05-26
    • 2020-07-18
    • 1970-01-01
    • 1970-01-01
    • 2017-04-19
    • 1970-01-01
    • 1970-01-01
    • 2018-06-07
    相关资源
    最近更新 更多