为什么我的 Regex 搜索产生的结果比预期的多,为什么我的循环没有删除某些重复项?

Why is my Regex search yielding more than expected and why isn't my loop removing certain duplicates?

我正在开发一个解析天气信息的程序。在我的这部分代码中,我尝试按时间顺序重新组织结果,然后再继续添加更多项目。

这些行中的时间通常是任何一行的前 4 位数字(前 2 位数字是日期,其他是小时)。例外是以 11010KT 开头的行,该行始终被假定为任何天气报告中的第一行,并且这些数字是风矢量而不是时间。

您会看到我正在删除此示例开头包含 TEMPO INTERPROB 的任何行,因为我希望将包含这些词的行添加到另一个重组列表的末尾。这些行可以被认为是一个单独的列表,我希望以与其他项目相同的方式按时间组织其中。

我正在尝试使用正则表达式从删除 TEMPO INTERPROB 行后剩余的行中提取时间,然后对它们进行排序,然后在排序后使用regex 再次完整地找到该行并创建一个重组列表。完成该列表后,我将对 TEMPO INTERPROB 列表进行排序,然后将其附加到我刚刚制作的新完成的列表中。

我还尝试了一个 for 循环,该循环将删除添加的任何重复行,但这似乎只删除了 TEMPO 行的一个副本???

有人可以帮我解决这个问题吗?我对此有点陌生,谢谢...

这理想情况下应该像这样回来:

ETA IS 0230 which is 1430 local

11010KT 5000 MODERATE DRIZZLE BKN004
FM050200 12012KT 9999 LIGHT DRIZZLE BKN008 
TEMPO 0501/0502 2000 MODERATE DRIZZLE BKN002
INTER 0502/0506 4000 SHOWERS OF MODERATE RAIN BKN008

取而代之的是,我重复了以 FM050200 开头的行,然后重复了以 TEMPO 开头的行。它也没有找到以 INTER 开头的行...

我做了一个最小的可复制示例,供任何人尝试帮助我。我将把它包括在这里:

import re

total_print = ['\nFM050200 12012KT 9999 LIGHT DRIZZLE BKN008', '\n11010KT 5000 MODERATE DRIZZLE BKN004', '\nINTER 0502/0506 4000 SHOWERS OF MODERATE RAIN BKN008', '\nTEMPO 0501/0502 2000 MODERATE DRIZZLE BKN002']

removed_lines = []
for a in total_print:  # finding and removing lines with reference to TEMPO INTER PROB
    if 'TEMPO' in a:
        total_print.remove(a)
        removed_lines.append(a)
for b in total_print:
    if 'INTER' in b:
        total_print.remove(b)
        removed_lines.append(b)
for f in total_print:
    if 'PROB' in f:
        total_print.remove(f)
        removed_lines.append(f)

list_time_in_line = []
for line in total_print: # finding the times in the remaining lines
    time_in_line = re.search(r'\d\d\d\d', line)
    list_time_in_line.append(time_in_line.group())
sorted_time_list = sorted(list_time_in_line)

removed_time_in_line = []
for g in removed_lines:  # finding the times in the lines that were originally removed
    removed_times = re.search(r'\d\d\d\d', g)
    removed_time_in_line.append(removed_times.group())
sorted_removed_time_list = sorted(removed_time_in_line)


final = []
final.append('ETA IS 1230 which is 1430 local\n')  # appending the time display
search_for_first_line = re.search(r'[\n]\d\d\d\d\dKT', ' '.join(total_print))  # searching for line that has wind vector instead of time
search_for_first_line = search_for_first_line.group()

if search_for_first_line:  # adding wind vector line so that its the firs line listed in the group
    search_for_first_line = re.search(r'%s.*' % search_for_first_line, ' '.join(total_print)).group()
    final.append('\n' + search_for_first_line)

print(sorted_time_list)  # the list of possible times found (the second item in list is the wind vector and not a time)
d = 0
for c in sorted_time_list:  # finding the whole line for the corresponding time
    print(sorted_time_list[d])
    search_for_whole_line = re.search(r'.*\w+\s*%s.*' % sorted_time_list[d], ' '.join(total_print))
    print(search_for_whole_line.group())  # it is doubling up on the 0502 time???????
    d += 1
    final.append('\n' + str(search_for_whole_line.group()))

h = 0
for i in sorted_removed_time_list:  # finding the whole line for the corresponding times from the previously removed items
    whole_line_in_removed_srch = re.search(r'.*%s.*' % sorted_removed_time_list[h], ' '.join(removed_lines))
    h += 1
    final.append('\n' + str(whole_line_in_removed_srch.group()))  # appending them

l_new = []
for item in final:  # this doesn't seeem to properly remove duplicates ?????
    if item not in l_new:
        l_new.append(item)
total_print = l_new

print(' '.join(total_print))

///////////////////////////////////// //编辑:

我最近问过这个问题,@diggusbickus 对我的问题给出了很好的答案。我现在遇到了答案排序的新问题。

因为我原来的问题在我的data['other']中只有一种天气线(以字母'FM'开头),所以lambdasplit()只是暂时查看行 [0] 的第一项。

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

时间所在的位置(在上一个问题中是 FM050200,其中 05 是日期,0200 是时间)。当有以 FM 开头的行时,这非常有效,但我意识到偶尔会存在这样的行:

'\nBECMG 0519/0520 27007KT 9999 SHOWERS OF LIGHT RAIN SCT020 BKN030'

这种行中的时间是位于索引 [1] 的前 4 位数字,并且采用 4 位格式而不是 FM050200 中的 6 位格式行。此新行中的时间是 05 作为日期,19 作为小时(所以 1900)。

我需要将这种样式的行与 FM 行分组,问题是它们无法排序。我正在尝试找到一种能够按时间对行进行排序的方法,而不管时间是在 [0] 索引上以 6 位格式还是在 [1] 索引上以 4 位格式。

我将包含一个新示例,其中对最初回答的问题进行了一些小改动。这个新问题将具有与 total_print 变量不同的数据。这是一个工作示例。

我基本上需要按任何行的前 4 位数字对行进行排序,结果应如下所示:

ETA IS 0230 which is 1430 local

FM131200 20010KT 9999 SHOWERS OF LIGHT RAIN SCT006 BKN010 
FM131400 20010KT 9999 SHOWERS OF LIGHT RAIN SCT006 BKN010 
BECMG 1315/1317 27007KT 9999 SHOWERS OF LIGHT RAIN SCT020 BKN030 
TEMPO 1312/1320 4000 SHOWERS OF MODERATE RAIN BKN007

注意。 TEMPO 行应该放在最后,所以不用担心那一行。

这是例子,非常感谢任何帮助的人。

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','\nTEMPO 1312/1320 4000 SHOWERS OF MODERATE RAIN BKN007']
data = {
    'windvector': [], # if it is the first line of the TAF
    'other': [], # anythin with FM or BECMG
    'tip': []  # tempo/inter/prob
}

wind_vector = re.compile('^\s\d{5}KT')
for line in total_print:
    if 'TEMPO' in line \
            or 'INTER' in line \
            or 'PROB' in line:
        key = 'tip'
    elif re.match(wind_vector, line):
        key = 'windvector'
    else:
        key = 'other'
    data[key].append(line)

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


final.append('ETA IS 0230 which is 1430 local\n')

for lst in data.values():
    for line in lst:
        final.append('\n' + line[1:])  # get rid of newline

print(' '.join(final))

只需将您的数据排序到字典中,您总是在创建列表并删除项目:这太混乱了。

用于捕获风矢量的正则表达式也捕获 12012KT,这就是重复该行的原因。 ^ 确保它只匹配你的模式,如果它是行的开头

import re

total_print = ['\nFM050200 12012KT 9999 LIGHT DRIZZLE BKN008', '\n11010KT 5000 MODERATE DRIZZLE BKN004', '\nINTER 0502/0506 4000 SHOWERS OF MODERATE RAIN BKN008', '\nTEMPO 0501/0502 2000 MODERATE DRIZZLE BKN002']

data = {
    'windvector': [],
    'other': [],
    'tip': [] #tempo/inter/prob
}

wind_vector=re.compile('^\s\d{5}KT')
for line in total_print:
    if 'TEMPO' in line \
            or 'INTER' in line \
            or 'PROB' in line:
        key='tip'
    elif re.match(wind_vector, line):
        key='windvector'
    else:
        key='other'
    data[key].append(line)
        
data['tip']=sorted(data['tip'], key=lambda x: x.split()[1])
print('ETA IS 0230 which is 1430 local')
print()
for lst in data.values():
    for line in lst:
        print(line[1:]) #get rid of newline