【问题标题】:Why is my Regex search yielding more than expected and why isn't my loop removing certain duplicates?为什么我的正则表达式搜索产生的结果超出预期,为什么我的循环没有删除某些重复项?
【发布时间】:2021-12-19 05:05:15
【问题描述】:

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

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

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

我正在尝试使用正则表达式从删除 TEMPO INTERPROB 行后剩余的行中提取时间,然后对它们进行排序,然后排序后,再次使用正则表达式完整地找到该行并创建一个重组列表。完成该列表后,我将对 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”开头),所以带有split()lambda 只查看@987654341 行的第一项@时间。

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))

【问题讨论】:

  • 那肯定不像 MRE。在任何情况下,你都不应该从你正在迭代的东西中删除项目。
  • 那么你会怎么做呢?那你能帮忙提供一个解决方案吗?

标签: python regex duplicates append re


【解决方案1】:

只需将您的数据排序到一个字典中,您总是在创建列表和删除项目:这太令人困惑了。

你捕捉风向量的正则表达式也捕捉到了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

【讨论】:

  • 我非常感谢这个答案,它非常好用,谢谢。请查看我的编辑,因为您可能对我有答案......
  • 事情并非如此。这是一个不同的问题,问一个新的问题
猜你喜欢
  • 2015-07-24
  • 2020-09-23
  • 2019-02-03
  • 2013-11-21
  • 1970-01-01
  • 2022-11-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多