【问题标题】:How can I sort list lines by time if the times are in different locations in the line?如果时间在行中的不同位置,如何按时间对列表行进行排序?
【发布时间】:2021-12-26 12:18:03
【问题描述】:

我一直在制作一个对天气数据行进行排序的程序。需要按时间顺序对数据行进行排序。我收到一份格式稍有不同的天气线列表,根据天气行为和变化发生的速度,这条线将以FMBECMG 开头。

我能够对每次列出的时间都在同一索引位置(索引 [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 开头,如何按时间顺序对行进行排序?我应该使用正则表达式并隔离时间吗?有人可以帮忙吗,我卡住了吗?

【问题讨论】:

  • 既然只有2种格式,那么先提取时间再对字符串进行排序呢? :")

标签: python list sorting indexing split


【解决方案1】:

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

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']

【讨论】:

  • 这很好用,非常感谢@Ron Serruya !!!
【解决方案2】:

如果该行以'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'

【讨论】:

    猜你喜欢
    • 2010-11-28
    • 2010-11-28
    • 2021-12-20
    • 2013-07-16
    • 1970-01-01
    • 2011-03-16
    • 2019-03-12
    相关资源
    最近更新 更多