结合两个列表并通过引用字典Python进行排序

时间:2012-12-11 15:53:02

标签: python regex debugging sorting dictionary

我(在我看来是)一个非常复杂的问题。我将尝试尽可能简洁 - 尽管为了完全理解这个问题,您可能必须单击我的个人资料并查看我在StackOverflow上发布的两个问题(仅限其他)。简而言之:我有两个列表 - 一个包含包含设施名称的电子邮件字符串和事件日期。另一个由每个电子邮件的工具ID组成(我使用以下正则表达式函数之一来获取此列表)。我已经使用Regex来搜索每个字符串以获取这些信息。 3个正则表达式函数是:

def find_facility_name(incident):

    pattern = re.compile(r'Subject:.*?for\s(.+?)\n')
    findPat1 = re.search(pattern, incident)
    facility_name = findPat1.group(1)

    return facility_name



def find_date_of_incident(incident):


    pattern = re.compile(r'Date of Incident:\s(.+?)\n')
    findPat2 = re.search(pattern, incident)
    incident_date = findPat2.group(1)

    return incident_date

def find_facility_id(incident):
    pattern = re.compile('(\d{3})\n')
    findPat3 = re.search(pattern, incident)
    f_id = findPat3.group(1)

    return f_id

我还有一个格式如下的字典:

d = {'001' : 'Facility #1', '002' : 'Another Facility'...etc.}

我正在尝试组合这两个列表,并按字典中的键值排序,然后是事件日期。由于键值附加到设施名称,因此应自动将来自相同设施的电子邮件组合在一起。为此,我尝试使用这两个函数:

def get_facility_ids(incident_list):
'''(lst) -> lst

Return a new list from incident_list that inserts the facility IDs from the
get_facilities dictionary into each incident.

'''
f_id = []
for incident in incident_list:
    find_facility_name(incident)
    for k in d:
        if find_facility_name(incident) == d[k]:
            f_id.append(k)

return f_id

id_list = get_facility_ids(incident_list)

def combine_lists(L1, L2):
    combo_list = []
    for i in range(len(L1)):
        combo_list.append(L1[i] + L2[i])

return combo_list

combination = combine_lists(id_list, incident_list)

def get_sort_key(incident):
'''(str) -> tup

Return a tuple from incident containing the facility id as the first
value and the date of the incident as the second value.

'''

return (find_facility_id(incident), find_date_of_incident(incident))

final_list = sorted(combination, key=get_sort_key)

以下是我输入的内容和所需输出的示例:

d = {'001' : 'Facility #1', '002' : 'Another Facility'...etc.}
input: first_list = ['email_1', 'email_2', etc.]
first output: next_list = ['facility_id_for_1+email_1', 'facility_id_for_2 + email_2', etc.]
DESIRED OUTPUT: FINAL_LIST = sorted(next_list, key=facility_id, date of incident)

唯一的问题是,键值与每个单独的电子邮件字符串中找到的内容不匹配。有些DO,其他是完全随机的。我不知道为什么会这样,但我觉得它与我将这两个列表结合起来的方式有关。任何人都可以帮助这个卑微的n00b?感谢!!!

2 个答案:

答案 0 :(得分:0)

首先,我建议撤消你的ID到名字词典。按键查找值非常快,但按值查找键非常慢。

rd = { name: id_num for id_num, name in d.items() }

然后你的第一个函数可以用列表解析代替:

id_list = [rd[find_facility_name(incident)] for incident in incident_list]

这也可能会暴露为什么你在结果中搞砸了值。如果事件的设施名称不在您的字典中,则此代码将引发KeyError(而您的旧功能只会跳过它)。

您的combine函数与Python内置的zip函数非常相似。我将其替换为:

combination = [id+incident for id, incident in zip(id_list, incident_list)]

但是,由于您要从第二个列表构建第一个列表,因此直接构建组合版本可能是有意义的,而不是单独创建列表,然后在单独的步骤中组合它们。这是对上面列表理解的更新,直接到combination结果:

combination = [rd[find_facility_name(incident)] + incident
               for incident in incident_list]

要进行排序,您可以使用我们刚刚添加到电子邮件消息中的ID字符串,而不是解析以再次查找ID:

combination.sort(key=lambda x: (x[0:3], get_date_of_incident(x)))

切片中的3基于"001""002"的示例作为id值。如果实际ID更长或更短,则需要对其进行调整。

答案 1 :(得分:0)

所以,我认为这是正在发生的事情。请尽可能纠正我。 'incident_list'是电子邮件字符串列表。您进入并在每封电子邮件中找到设施名称,因为您有一个外部字典,其中包含(key:value)=(设施ID:设施名称)。从字典中,您可以在此“id_list”中提取工具ID。

您组合列表以便获得字符串列表[设施ID +电子邮件,...] 然后你希望它按元组排序(设施ID,发生日期)。

看起来您正在搜索设施ID和设施名称两次。如果它们相同,您可以跳过一个步骤。然后,最好的方法是使用元组一次完成所有操作:

incident_list = ['email1', 'email2',...]

unsorted_list = []
for email in incident list:
    id = find_facility_id(email)
    date = find_date_of_incident(email)
    mytuple = ( id, date, id + email )
    unsorted_list.append(mytuple)

final_list = sorted(unsorted_list, key=lambda mytup:(mytup[0], mytup[1]))

然后你得到一个简单的元组列表,按第一个元素(id作为字符串)排序,然后是第二个元素(date作为字符串)。如果你只需要一个字符串列表(id + email),那么你需要一个列表,其中包含每个元组部分的最后一个元素

FINALLIST = [ tup[-1] for tup in final_list ]