按值对字符串排序并添加到列表

时间:2019-02-26 15:47:12

标签: python list sorting

我有这个日志文件列表,我想按每个文件中的日期进行排序:如您所见,LOG_之后是一个数字,这是我要对字符串进行排序的键。

日期为yyyymmdd格式。

LOGS\LOG_20190218_91_02.LOG
LOGS\LOG_20190218_91_05.LOG
LOGS\LOG_20190218_91_00.LOG
LOGS\LOG_20190218_91_22.LOG
LOGS\LOG_20190218_91_10.LOG
LOGS\LOG_20190219_56_22.LOG
LOGS\LOG_20190219_56_24.LOG
LOGS\LOG_20190219_56_25.LOG
LOGS\LOG_20190219_56_26.LOG
LOGS\LOG_20190219_56_03.LOG
LOGS\LOG_20190220_56_22.LOG
LOGS\LOG_20190220_56_07.LOG
LOGS\LOG_20190220_56_13.LOG
LOGS\LOG_20190220_56_17.LOG
LOGS\LOG_20190220_56_21.LOG

我尝试了各种方法:

  1. 提取日期值,将其添加到列表中,将它们分开(使用set),然后分别取字符串/文件路径并将其添加到列表中。问题在于日期的大小可能会有所不同(这里只有3个,但可能会更多)。因此,使用固定列表(可能)超出了范围。

  2. 验证每个字符串,然后检查上一个/下一个,以查看日期是否更改。如果更改,则将所有先前的路径/字符串添加到列表中。仍然是同样的问题,但也许可以改进这种方法。

  3. 手动复制每个日期的文件夹中的文件,然后使用它们。到目前为止,这已超出范围,因为我们正在谈论的是大文件(演出)。

我想了解的是如何实现第二种解决方案。如何将具有相同日期的文件/字符串正确存储在自己的列表中?

预期结果...

list20190218 = [all LOG files with 20190218 value in name]
list20190219 = [all LOG files with 20190219 value in name]
list20190220 = [all LOG files with 20190220 value in name]

...但列表数量可变。

谢谢

3 个答案:

答案 0 :(得分:2)

一种干净的方法是使用字典。在这种情况下,键将是日期,值将是相应的列表。为了对列表中的元素进行分组,可以使用itertools.groupby。您还需要指定要使用日期对列表进行分组,因为您可以从key参数中的每个字符串中提取日期子字符串:

from itertools import groupby
from operator import itemgetter

d = {k:list(v) for k,v in groupby(data, key=lambda x: itemgetter(1)(x.split('_')))}

然后只需:

d['20190220']

['LOGS\\LOG_20190220_56_22.LOG\n',
 'LOGS\\LOG_20190220_56_07.LOG\n',
 'LOGS\\LOG_20190220_56_13.LOG\n',
 'LOGS\\LOG_20190220_56_17.LOG\n',
 'LOGS\\LOG_20190220_56_21.LOG']

答案 1 :(得分:2)

下面的代码。

创建一个命名元组,该元组将保留文件日期。使用日期作为键对列表进行排序。

from collections import namedtuple, defaultdict
import datetime

FileAttr = namedtuple('FileAttr', 'name date')
files = ['LOGS\LOG_20190218_91_02.LOG',
         'LOGS\LOG_20190218_91_05.LOG',
         'LOGS\LOG_20190218_91_00.LOG',
         'LOGS\LOG_20190218_91_22.LOG',
         'LOGS\LOG_20190218_91_10.LOG',
         'LOGS\LOG_20190219_56_22.LOG',
         'LOGS\LOG_20190219_56_24.LOG',
         'LOGS\LOG_20190219_56_25.LOG',
         'LOGS\LOG_20190219_56_26.LOG',
         'LOGS\LOG_20180219_56_26.LOG',
         'LOGS\LOG_20170219_56_26.LOG',
         'LOGS\LOG_20190219_56_03.LOG',
         'LOGS\LOG_20190220_56_22.LOG',
         'LOGS\LOG_20190220_56_07.LOG',
         'LOGS\LOG_20190220_56_13.LOG',
         'LOGS\LOG_20190220_56_17.LOG',
         'LOGS\LOG_20190220_56_21.LOG']
files_ex = []

for f in files:
    left_idx = f.find('_')
    right_idx = f.find('.')
    date_part = f[left_idx + 1:right_idx][:-6]
    year = int(date_part[:4])
    month = int(date_part[4:6])
    day = int(date_part[6:8])
    dt = datetime.datetime(year, month, day)
    files_ex.append(FileAttr(f, dt))
sorted_files_ex = sorted(files_ex, key=lambda x: x[1])

files_by_date = defaultdict(list)
for file_attr in sorted_files_ex:
    files_by_date[file_attr.date].append(file_attr.name)
for date, files in files_by_date.items():
    print('{} --> {}'.format(date, files))

输出:

2019-02-18 00:00:00 --> ['LOGS\\LOG_20190218_91_02.LOG', 'LOGS\\LOG_20190218_91_05.LOG', 'LOGS\\LOG_20190218_91_00.LOG', 'LOGS\\LOG_20190218_91_22.LOG', 'LOGS\\LOG_20190218_91_10.LOG']
2019-02-19 00:00:00 --> ['LOGS\\LOG_20190219_56_22.LOG', 'LOGS\\LOG_20190219_56_24.LOG', 'LOGS\\LOG_20190219_56_25.LOG', 'LOGS\\LOG_20190219_56_26.LOG', 'LOGS\\LOG_20190219_56_03.LOG']
2017-02-19 00:00:00 --> ['LOGS\\LOG_20170219_56_26.LOG']
2018-02-19 00:00:00 --> ['LOGS\\LOG_20180219_56_26.LOG']
2019-02-20 00:00:00 --> ['LOGS\\LOG_20190220_56_22.LOG', 'LOGS\\LOG_20190220_56_07.LOG', 'LOGS\\LOG_20190220_56_13.LOG', 'LOGS\\LOG_20190220_56_17.LOG', 'LOGS\\LOG_20190220_56_21.LOG']

答案 2 :(得分:0)

我还将发布我的解决方案。它更冗长,但可能比列表理解更容易理解。

import os
import glob
from itertools import groupby
from operator import itemgetter

LOGS = ['LOGS\LOG_20190218_91_02.LOG',
        'LOGS\LOG_20190218_91_05.LOG',
        'LOGS\LOG_20190218_91_00.LOG',
        'LOGS\LOG_20190218_91_22.LOG',
        'LOGS\LOG_20190218_91_10.LOG',
        'LOGS\LOG_20190219_56_22.LOG',
        'LOGS\LOG_20190219_56_24.LOG',
        'LOGS\LOG_20190219_56_25.LOG',
        'LOGS\LOG_20190219_56_26.LOG',
        'LOGS\LOG_20190219_56_03.LOG',
        'LOGS\LOG_20190220_56_22.LOG',
        'LOGS\LOG_20190220_56_07.LOG',
        'LOGS\LOG_20190220_56_13.LOG',
        'LOGS\LOG_20190220_56_17.LOG',
        'LOGS\LOG_20190220_56_21.LOG']

dateList = []

for log in LOGS:
    baseName = os.path.basename(log)
    date = baseName.split('_')[1][:8]
    dateList .append(date)

dateList = (set(dateList))

myDict = {}

for date in dateList:
    for log in LOGS:
        if date in log:
            myDict.setdefault(date, [])

            myDict[date].append(log)

for key, value in myDict.items():
    print(key, value)

输出:

20190220 ['LOGS\\LOG_20190220_56_22.LOG', 'LOGS\\LOG_20190220_56_07.LOG', 'LOGS\\LOG_20190220_56_13.LOG', 'LOGS\\LOG_20190220_56_17.LOG', 'LOGS\\LOG_20190220_56_21.LOG']
20190219 ['LOGS\\LOG_20190219_56_22.LOG', 'LOGS\\LOG_20190219_56_24.LOG', 'LOGS\\LOG_20190219_56_25.LOG', 'LOGS\\LOG_20190219_56_26.LOG', 'LOGS\\LOG_20190219_56_03.LOG']
20190218 ['LOGS\\LOG_20190218_91_02.LOG', 'LOGS\\LOG_20190218_91_05.LOG', 'LOGS\\LOG_20190218_91_00.LOG', 'LOGS\\LOG_20190218_91_22.LOG', 'LOGS\\LOG_20190218_91_10.LOG']

如果您使用print(myDict["20190220"]) ...

['LOGS\\LOG_20190220_56_22.LOG', 'LOGS\\LOG_20190220_56_07.LOG', 'LOGS\\LOG_20190220_56_13.LOG', 'LOGS\\LOG_20190220_56_17.LOG', 'LOGS\\LOG_20190220_56_21.LOG']