按名称(月份)排序字符串列表

2 投票
3 回答
2322 浏览
提问于 2025-04-16 07:48

我有一份文件名的列表,想用Python创建一个文本文件,把这些名字按特定的顺序列出来(是为了制作电影用的)。这里面有一些文件名是月份的,比如四月、八月等等。我希望能把一月的放在最前面,然后是二月,以此类推。

我知道可以用一种比较笨的方法来实现,但我想找一种既优雅又通用的解决方案。

我的文件名,按自然顺序排列如下:
cld_for_April_EISopt_1000.png
cld_for_August_EISopt_1000.png
cld_for_December_EISopt_1000.png
cld_for_February_EISopt_1000.png
cld_for_January_EISopt_1000.png
cld_for_July_EISopt_1000.png
cld_for_June_EISopt_1000.png
cld_for_March_EISopt_1000.png
cld_for_May_EISopt_1000.png
cld_for_November_EISopt_1000.png
cld_for_October_EISopt_1000.png
cld_for_September_EISopt_1000.png

我希望文本文件的内容是这样的:
cld_for_January_EISopt_1000.png
cld_for_February_EISopt_1000.png
cld_for_March_EISopt_1000.png
cld_for_April_EISopt_1000.png
cld_for_May_EISopt_1000.png
cld_for_June_EISopt_1000.png
cld_for_July_EISopt_1000.png
cld_for_August_EISopt_1000.png
cld_for_September_EISopt_1000.png
cld_for_October_EISopt_1000.png
cld_for_November_EISopt_1000.png
cld_for_December_EISopt_1000.png

或者更一般地说,如果我有一个列表、数组或者字典,比如:
{'pattern1': rank_in_output_list_1, ..., 'pattern12': rank_in_output_list_12}
我该怎么做才能用它来排序我的文件名呢?

到目前为止,我尝试过:os.listdir、os.path.isfile、numpyp.ma.array、.compressed() 或 .compress();但都没有成功。

非常感谢!
Christophe。

3 个回答

0

这是我的最终版本。
我希望它更符合Python的风格。

欢迎大家对整体风格提出意见。

#!/usr/bin/env python
"""Demonstrate how to animate multiple figures into a climatology movie."""

#
# Imports
#
from os import system
from os.path import exists
from numpy import ma
from glob import glob
from copy import deepcopy
from logging import warning

#
# Parameters
#
month_list = ['January',
              'February',
              'March',
              'April',
              'May',
              'June',
              'July',
              'August',
              'September',
              'October',
              'November',
              'December']
#
month_dict = {'January': 0, 
              'February': 1, 
              'March': 2, 
              'April': 3, 
              'May': 4, 
              'June': 5, 
              'July': 6,
              'August': 7, 
              'September': 8, 
              'October': 9, 
              'November': 10, 
              'December': 11}
#
param_dict_default = {'fig_folder': 'figures/era40_correlations/',
                      'output_name': 'output_sol_2.mp4',
                      'fig_criteria': '*climatology*isccp*.png',
                      'order': month_list,
                      'input_file': 'list_fig_for_movie.txt',
                      'splitor': '_',
                      'fps': 10}

#
# Functions
#
def reorder(seq, extractor, order):
    "Reorder 'seq' using 'extractor' and according to 'order'."""
    rank = dict((v,i) for i,v in enumerate(order))
    return sorted(seq, key=lambda v: rank.get(extractor(v),-1))

def get_ordering_key(filename, splitor, ind):
    """Get ordering key in 'filename' at 'ind' position for 'splitor'."""
    return filename.split(splitor)[ind]

def prepareMovie(param_dict={}):
    """Return the command line to create the movie and the output filename.

    Input
    -----
    param_dict : dictionary with parameters for creating the movie.
    Keys:              Default values:
     *  fig_criteria    = '*climatology*isccp*.png'
     *  input_file      = 'list_fig_for_movie.txt'
     *  splitor         = '_'
     *  fps             = 10
     *  fig_folder      = 'figures/era40_correlations/'
     *  output_name     = 'output_sol_2.mp4'
     *  order           = ['January', 'February', 'March', 'April',
                           'May', 'June', 'July', 'August', 'September',
                           'October', 'November', 'December']
    from:
    for key in param_dict_default.keys():
        print ' * ', key, '=', repr(param_dict_default[key])

    Output
    ------
    Command line to create the movie and output filename.
    """

    # Update parameters
    param_new = deepcopy(param_dict_default)
    param_new.update(param_dict)
    # List all selected figures
    file_names = glob(param_new['fig_folder'] + param_new['fig_criteria'])
    # Find position of ordering key in name
    for item in param_new['order']:
        try:
            ind = file_names[0].split(param_new['splitor']).index(item)
        except:
            pass
    # Sort all selected figures
    if isinstance(param_new['order'], list):
        file_names = sorted(file_names, key=lambda x: param_new['order'].\
                    index(x.split(param_new['splitor'])[ind]))
    elif isinstance(param_new['order'], dict):
        file_names = sorted(file_names, key=lambda x: param_new['order']\
                    [x.split(param_new['splitor'])[ind]])
    else:
        raise ValueError("param_dict['order'] must be list or dictionary.")
    # Remove input file for mencoder if already exists
    if exists(param_new['input_file']):
        warning(" '%s' existed and has been overwritten."
                %param_new['input_file'])
        system("rm %s" %param_new['input_file'])
    # Write input file for mencoder
    f = open(param_new['input_file'], "w")
    for item in file_names:
        f.write(item+'\n')
    f.close()
    # Create command for mencoder
    command = ['mencoder',
               'mf://@' + param_new['input_file'],
               '-mf',
               "type=png:w=800:h=600:fps=%s" %param_new['fps'],
               '-ovc',
               'lavc',
               '-lavcopts',
               'vcodec=mpeg4',
               '-oac',
               'copy',
               '-o',
               param_new['output_name']]
    # Make it one line white-spaced and return it
    command = ''.join([item + ' ' for item in command])
    return command, param_new['output_name']

#
# Main
#
if __name__ == "__main__":
    [command, output_name] = prepareMovie()
    # Create the movie
    system(command)
    # Open it
    system("mplayer %s" %output_name)
6

作为排序的关键,先用 _ 来分割,然后取第三个元素。

sorted(filenames, key=lambda x: monthdict[x.split('_')[2]])
1

这是一个更长但更灵活的关于如何排序序列的回答:

import collections

def rearrange(seq, order, keyfunc):
    if not isinstance(order, collections.Mapping):
        order = {v: i for i,v in enumerate(order)}
    return sorted(seq, key=lambda x: order[keyfunc(x)])

if __name__ == '__main__':
    filenames = """
        cld_for_April_EISopt_1000.png    cld_for_August_EISopt_1000.png
        cld_for_December_EISopt_1000.png cld_for_February_EISopt_1000.png
        cld_for_January_EISopt_1000.png  cld_for_July_EISopt_1000.png
        cld_for_June_EISopt_1000.png     cld_for_March_EISopt_1000.png
        cld_for_May_EISopt_1000.png      cld_for_November_EISopt_1000.png
        cld_for_October_EISopt_1000.png  cld_for_September_EISopt_1000.png
    """.split()

    months = ['January', 'February', 'March', 'April', 'May', 'June', 'July',
              'August', 'September', 'October', 'November', 'December']

    def get_month_name(filename):
        return filename.split('_')[2]

    for filename in rearrange(filenames, months, get_month_name):
        print(filename)

输出结果:

cld_for_January_EISopt_1000.png
cld_for_February_EISopt_1000.png
cld_for_March_EISopt_1000.png
cld_for_April_EISopt_1000.png
  ...

撰写回答