如果时间位于行中的不同位置,如何按时间对列表行进行排序?

How can I sort list lines by time if the times are in different locations in the line?

我一直在制作一个对天气数据行进行排序的程序。需要按时间顺序对数据行进行排序。我收到了一份天气线列表,这些天气线的格式彼此略有不同,并且根据天气行为和变化发生的速度,该线将以 FMBECMG.[=21 开头=]

我能够对列出的时间每次都位于同一索引位置(索引 [0])的天气行进行排序。例如:

FM131200 20010KT 5000 SHOWERS OF LIGHT RAIN SCT006 BKN010 

FM131400 20010KT 9999 SHOWERS OF LIGHT RAIN SCT006 FEW030

从上面的两个例子来看,第一个的时间显示的是该月的第 13 天,在 12:00。在第二个中,它是该月的第 14 天 14:00。这种格式很好,因为两者的时间索引在同一索引中,但是如果我遇到如下情况,我的排序将不起作用。

FM131400 20010KT 9999 SHOWERS OF LIGHT RAIN SCT006 BKN010

BECMG 1315/1317 27007KT 9999 SHOWERS OF LIGHT RAIN SCT020 BKN030

从上面的示例来看,第一行显然与前面的示例相同,但第二行在位置(索引[1])和格式上有所不同。第二行中的时间是该月的第 13 天 15:00。

我以这个为例,说明我现在如何按时间顺序对它们进行排序,但只有当该行的时间位于索引 [0] 时才有效。

import re

total_print = ['\nBECMG 1315/1317 27007KT 9999 SHOWERS OF LIGHT RAIN SCT020 BKN030', '\nFM131200 20010KT 9999 SHOWERS OF LIGHT RAIN SCT006 BKN010',
               '\nFM131400 20010KT 9999 SHOWERS OF LIGHT RAIN SCT006 BKN010']

data = {
    'other': [], # anything with FM or BECMG
}

for line in total_print:
    key = 'other'
    data[key].append(line)

final = []
data['other'] = sorted(data['other'], key=lambda x: x.split()[0])

for lst in data.values():
    for line in lst:
        final.append('\n' + line[1:])

print(' '.join(final))

这些行以随机顺序提供,有时全部以 BECMG 开头或全部以 FM 开头,有时两者兼而有之。所以我需要找到一种方法来对它们进行排序,不管它们是怎么来的。

无论行是以 FM 还是 BECMG 开头,如何按时间顺序对行进行排序?我应该使用 Regex 并隔离时间吗?有人可以帮忙吗,我被卡住了?

您可以使用正则表达式提取时间,然后将此时间作为“关键字”进行排序

import re

pattern = r"((?<=FM)\d{6})|(?<=BECMG )\d{4}"
matcher = re.compile(pattern)

data = ['FM131200 20010KT 5000 SHOWERS OF LIGHT RAIN SCT006 BKN010 ',
 'FM131400 20010KT 9999 SHOWERS OF LIGHT RAIN SCT006 FEW030',
 'BECMG 1315/1317 27007KT 9999 SHOWERS OF LIGHT RAIN SCT020 BKN030',
 'FM131400 20010KT 9999 SHOWERS OF LIGHT RAIN SCT006 BKN010']

print(sorted(data, key=lambda item: matcher.search(item).group()))

这将打印:

['FM131200 20010KT 5000 SHOWERS OF LIGHT RAIN SCT006 BKN010 ',
 'FM131400 20010KT 9999 SHOWERS OF LIGHT RAIN SCT006 FEW030',
 'FM131400 20010KT 9999 SHOWERS OF LIGHT RAIN SCT006 BKN010',
 'BECMG 1315/1317 27007KT 9999 SHOWERS OF LIGHT RAIN SCT020 BKN030']

如果该行以'FM'开头,则时间为该行的第2、3、4、5个字符。如果该行以 BECMG 开头,则时间为该行的第 6、7、8、9 个字符。

您可以将其用作排序的关键字:

data = ['\nFM131200 20010KT 5000 SHOWERS OF LIGHT RAIN SCT006 BKN010 ',
 '\nFM131400 20010KT 9999 SHOWERS OF LIGHT RAIN SCT006 FEW030',
 '\nBECMG 1315/1317 27007KT 9999 SHOWERS OF LIGHT RAIN SCT020 BKN030',
 '\nFM131400 20010KT 9999 SHOWERS OF LIGHT RAIN SCT006 BKN010']

data = [s.strip() for s in data]

def sorting_key(s):
  if s.startswith('FM'):
    return int(s[2:4]), int(s[4:6])
  elif s.startswith('BECMG'):
    return int(s[6:8]), int(s[8:10])
  else:
    raise ValueError(''.join(['Neither FM nor BECMG: ', s]))

data = sorted(data, key=sorting_key)

print(data)
# ['FM131200 20010KT 5000 SHOWERS OF LIGHT RAIN SCT006 BKN010',
#  'FM131400 20010KT 9999 SHOWERS OF LIGHT RAIN SCT006 FEW030',
#  'FM131400 20010KT 9999 SHOWERS OF LIGHT RAIN SCT006 BKN010',
#  'BECMG 1315/1317 27007KT 9999 SHOWERS OF LIGHT RAIN SCT020 BKN030']

当无法正确提取时间时,此代码将引发 ValueError

sorted(['hello'], key=sorting_key)
# ValueError: Neither FM nor BECMG: hello

sorted(['FM13hello'], key=sorting_key)
# ValueError: invalid literal for int() with base 10: 'he'