【问题标题】:Python: How to find most common elements of a list of filesPython:如何查找文件列表中最常见的元素
【发布时间】:2013-01-31 15:13:17
【问题描述】:

首先很抱歉这个简单的问题,但我想不出最简单的方法来编写我的问题。

我有一个目录,其中包含几个不同的文件,但具有共同的元素(values_25、_26、_28 等):

xxxxx_25.txt
xxxxx_26.txt
xxxxx_27.txt
xxxxx_28.txt
yyyyy_25.txt
yyyyy_26.txt
yyyyy_27.txt
yyyyy_29.txt
mmmmm_25.txt
mmmmm_26.txt
mmmmm_27.txt
mmmmm_30.txt

我希望得到列表

xxxxx_25.txt
yyyyy_25.txt
mmmmm_25.txt

xxxxx_26.txt
yyyyy_26.txt
mmmmm_26.txt

xxxxx_27.txt
yyyyy_27.txt
mmmmm_27.txt

xxxxx_28.txt

yyyyy_29.txt

mmmmm_30.txt

【问题讨论】:

  • 我不确定这个定义是否明确 -- 为什么不根据它们都以 .txt 结尾的事实将它们全部分组?
  • @Gianni: 下次,确切地指定你对输出的期望 - 我不知道你是否需要平面列表或嵌套列表,如果前缀排序确实如此事情等等。

标签: python optimization coding-style


【解决方案1】:
import re

list_with_file_names = 'xxxx_25.txt xxxxx_26.txt xxxxx_27.txt xxxxx_28.txt yyyyy_25.txt yyyyy_26.txt yyyyy_27.txt yyyyy_29.txt mmmmm_25.txt mmmmm_26.txt mmmmm_27.txt mmmmm_30.txt'.split()

def get_number_and_prefix(text):
    g = re.match('.*(\S+)(\d+)', text)
    return tuple([
        int(g.group(2)),
        g.group(1)])

nice_list = sorted(list_with_file_names, key=get_number_and_prefix)

get_number_and_prefix 返回的元组将首先按数字排序,然后按前缀排序

如果您想根据文件名中的数字进行分组,您可以使用以下内容:

def update_dict_with_file(dict_, filename):
    g = re.match('.*(\d+)', filename)
    key = g.group(1)
    t = dict_.setdefault(key,[])
    t.append(filename)

mydict = {}
[update_dict_with_file(mydict, filename) 
 for filename in list_with_file_names]

mydict 现在包含文件名中的数字作为键,以及文件名作为值的列表

编辑

总结到目前为止的所有答案,您所需要的只是从您的列表中构建一个sorted 列表,使用一个从文件名中提取您想要的任何内容的键 getter 函数。您可以通过带有itertools + 列表理解的花哨的单线或更长的for 循环(没有yieldanywhere?)来做到这一点。但是,基本上,它们都是一样的。没有火箭科学。

【讨论】:

    【解决方案2】:

    这样就可以了:

    list_of_files = [
        'xxxxx_25.txt',
        'xxxxx_26.txt',
        'xxxxx_27.txt',
        'xxxxx_28.txt',
        'yyyyy_25.txt',
        'yyyyy_26.txt',
        'yyyyy_27.txt',
        'yyyyy_29.txt',
        'mmmmm_25.txt',
        'mmmmm_26.txt',
        'mmmmm_27.txt',
        'mmmmm_30.txt',
        ]
    
    import re
    regex = re.compile('_([0-9]+)\.txt$')
    
    def keyfn(name):
        match = regex.search(name)
        if match is None:
            return None
        else:
            return match.group(1)
    
    import itertools
    for (key, group) in itertools.groupby(sorted(list_of_files,key=keyfn),keyfn):
        print [x for x in group]
    

    或者如果您想要一个列表作为结果,请将 for 循环替换为:

    [x for g in itertools.groupby(sorted(list_of_files,key=keyfn),keyfn) for x in g[1]]
    

    【讨论】:

      【解决方案3】:
      #Considering your list of files is as follows
      ur_file_list = """xxxxx_25.txt
      xxxxx_26.txt
      xxxxx_27.txt
      xxxxx_28.txt
      yyyyy_25.txt
      yyyyy_26.txt
      yyyyy_27.txt
      yyyyy_29.txt
      mmmmm_25.txt
      mmmmm_26.txt
      mmmmm_27.txt
      mmmmm_30.txt"""
      #Based on the pattern, you can get the key assuming, you need the part in the
      #filename (without ext) after underscore. So this will give you the part without regex
      key = lambda e: os.path.splitext(e)[0].split("_")[-1]
      from itertools import groupby
      #On a sorted list, group on the above key function
      #And generate a list of these groups
      [list(group) for _, group in groupby(sorted(ur_file_list.splitlines(), key = key), key = key)]
      [['xxxxx_25.txt', 'yyyyy_25.txt', 'mmmmm_25.txt'], ['xxxxx_26.txt', 'yyyyy_26.txt', 'mmmmm_26.txt'], ['xxxxx_27.txt', 'yyyyy_27.txt', 'mmmmm_27.txt'], ['xxxxx_28.txt'], ['yyyyy_29.txt'], ['mmmmm_30.txt']]
      

      【讨论】:

        【解决方案4】:

        collections.defaultdict 的使用对于这项任务非常方便。

        In [1]: import re; from collections import defaultdict
        
        In [2]: filenames
        Out[2]: 
        ['xxxxx_25.txt',
         'xxxxx_26.txt',
         'xxxxx_27.txt',
         'xxxxx_28.txt',
         'yyyyy_25.txt',
         'yyyyy_26.txt',
         'yyyyy_27.txt',
         'yyyyy_29.txt',
         'mmmmm_25.txt',
         'mmmmm_26.txt',
         'mmmmm_27.txt',
         'mmmmm_30.txt']
        
        In [3]: d = defaultdict(list)
        
        In [4]: for filename in filenames:
          ....:     m = re.search(r'_(\d+)\.txt$', filename)
          ....:     if m:
          ....:         d[m.group(1)].append(filename)
        
        In [5]: [sorted(filename_list) for filename_list in d.values()]
        Out[5]: 
        [['xxxxx_25.txt', 'yyyyy_25.txt'],
         ['mmmmm_26.txt', 'xxxxx_26.txt', 'yyyyy_26.txt'],
         ['mmmmm_27.txt', 'yyyyy_27.txt'],
         ['xxxxx_28.txt'],
         ['yyyyy_29.txt'],
         ['mmmmm_30.txt']]
        

        【讨论】:

          猜你喜欢
          • 2010-12-03
          • 1970-01-01
          • 1970-01-01
          • 2018-09-11
          • 1970-01-01
          相关资源
          最近更新 更多