Python - 匹配/比较两个数据/元组列表

时间:2016-10-31 10:56:53

标签: python django

我有两组数据,一组来自django中的查询集,它将返回如下数据:

sr_data =  ShowroomConfigData.objects.only('location').filter(is_showroom=True).exclude(location='MajorSite')
for i in sr_data:
    print i.location

London
Glasgow
Edinbrugh
...

第二组数据来自外部Mysql查询,该查询返回元组列表:

query = """long mysql query..."""
cur.execute(query)
esr_data = cur.fetchall()
for i in esr_data:
    print i[3]

London
Glasgow
Edinburgh
...

esr_data示例:

('John Smith', '0123456789', 'billy', 'London', 'London', datetime.date(2014, 12, 19), '0123456789', 'Bobs Builders', '123 place', 'city', 'add', 'London', 'LDN 103', ', '', '', ' ', '', '', ' ', ' ', ' ', ' ', '', ' ', '')

他们也不一定按顺序排列,我认为两者的顺序都是随机的。

但外部查询有一些我想定期导入django的细节。

所以我需要循环两个列表并在匹配时将数据导入django,唯一的问题是,循环它们可能永远不会匹配。

有谁知道我可以做这项工作的方法?

由于

3 个答案:

答案 0 :(得分:1)

所以,据我所知,你有2个变量,它们都是iterables。它们包含一些值,您希望在与另一个项目匹配时找到一个项目。

所以,一种天真的做法是:

for i in esr_data:
    for j in sr_data:
        if i[3] == j.location:
            # Import into django as they match

但这不是很好,因为它是O(M * N),其中M是esr_data的数字,N是sr_data的数字

你M和N非常大吗?如果没有,这可能会奏效。

要降低大数据的复杂性,首先要找到两者中的公共位置:

common_locations = set(d.location for d in sr_data) & set(d[3] for d in esr_data)
new_sr_data = filter(lambda d: d.location in common_locations,
                     sr_data) 
new_esr_data = filter(lambda d: d[3] in common_locations,
                      esr_data) 
for i in new_esr_data:
    for j in new_sr_data:
        if i[3] == j.location:
            # Import into django as they match

这降低了O(L * L)的复杂性,其中L是公共元素的数量。

答案 1 :(得分:0)

看起来esr_data返回一个元素元组,而不是元组列表。

所以你只需要比较类似元素的列表。你可以为此设置:

result = list(set(sr_data).intersection(esr_data))

答案 2 :(得分:0)

阅读完其他答案后,我开始质疑自己的假设,并认为实际的查询更多:

两个元组列表,根据特定字段查找两者中的行(例如:字段1,3和5都匹配)

基于该问题,您可以从第一个列表构建一组“匹配的位”,然后从第二个中拉出与该集合中的任何内容匹配的项目,例如,基于第一个列表的以下过滤器和每个元组中的最后一项:

x = [(1,2,3),(2,3,4),(3,4,5),(4,5,6)]
y = [(2,9,4),(4,9,6),(7,8,9),(1,1,1)]

set_x = set((i[0], i[2]) for i in x) # Set of unique keys in x

for item in y:
    if (item[0], item[2]) in set_x:
         pass # Do some importing here

我在下面列出了我的原始答案,以防它被使用。

基于问题的假设:

  • 元组有两个迭代
  • 每个列表中的“匹配”元组包含所有相同的值,但顺序不同(即:字段的顺序不同,但值的数量相同,所有这些值都需要匹配)
  • 您想要在两个原始列表中存在值的情况下导入新的元组列表吗?

一种选择是将元组列表转换为(冻结)集合,然后简单地拉出交集 - 即:两个集合中存在的所有集合。例如:

x = [(1,2,3),(2,3,4),(3,4,5),(4,5,6)]
y = [(2,3,4),(4,5,6),(7,8,9),(1,1,1)]
set_x = set(frozenset(i) for i in x)
set_y = set(frozenset(i) for i in y)
matches = set_x.intersection(set_y)