比较两个元组列表

时间:2017-04-06 13:29:51

标签: python list tuples list-comprehension

old = [('ver','1121'),('sign','89'),('address','A45'),('type','00')]
new = [('ver','1121'),('sign','89'),('type','01')]

我需要根据元组的第一个元素将new列表与old列表进行比较,并显示列表new列表之间的差异,以便输出看起来如此像:

Match     : ver   =   1121
Match     : sign  =   89
Mismatch  : type  =   01 (old : 00)

我可以通过下面的列表理解得到所有匹配的元组,但除此之外无法思考。

my_list = [(a,b) for (a,b) in new for (c,d) in old  if ((a==c) and (b==d))]
print( my_list)

请建议我这样做。

修改

我很抱歉没有明确我的问题,我没有提到一件事,列表中的键可能是重复的,这意味着列表可能是这样的:

old = [('ver','1121'),('sign','89'),('address','A45'),('type','00'),('ver','sorry')]

new = [('ver','1121'),('sign','89'),('type','01'),('ver','sorry)]

更新

感谢@holdenweb,我对他的代码进行了一些更改,这似乎提供了预期的输出,请提示是否有任何缺陷。

old = [('ver','1121'),('sign','89'),('address','A45'),('type','00'),('ver','works?')]
new = [('ver','1121'),('sign','89'),('type','01'),('ver','This')]

formatter = "{:12}: {:8} = {}".format
newfmter = "{} (old : {})".format

kv_old = []
for i,(kn, vn) in enumerate(new):
    vo = [(j,(ko,vo)) for j,(ko, vo) in enumerate(old) if (ko==kn) ]
    for idx,(key,val) in vo:
        if idx >=i:
            kv_old = [key,val]
            break;

    if kv_old[1]==vn:
        print(formatter("Match", kv_old[0], kv_old[1]))
    else:
        print(formatter("Mismatch", kn, newfmter(vn, kv_old[1])))

5 个答案:

答案 0 :(得分:5)

您可以使用$data = json_decode($topDegrees[1]["diplomas"],true);

set

答案 1 :(得分:1)

有时列表理解不是的答案。这可能是其中之一。此外,您不会处理#include <stdio.h> #include <iostream> using namespace std; void sort_with_show(int **a, int rozmiar, int polecenie) { int y, d; for (int i = 0; i< rozmiar - 1; i++) { for (int j = 0; j < rozmiar - 1 - i; j++) { if (a[j + 1][0] < a[j][0]) { y = a[j][0]; a[j][0] = a[j + 1][0]; a[j + 1][0] = y; } } } for (int i = 0; i < rozmiar; i++) { //cout << tablica[i].x << " " << tablica[i].y << "\n"; if (polecenie == 0) { cout << a[i][0] << '\n'; } else if (polecenie == 1) { cout << a[i][0] << "," << a[i][1] << "\n"; } } } int main() { int rozmiar = 0; int polecenie = 0; char t[20] = { '\0' }; char *p, *q; int liczba = 0; int calaLiczba = 0; bool isY = false; cin >> rozmiar; int ** a = new int *[rozmiar]; for (int i = 0; i < rozmiar; i++) a[i] = new int[2]; cin.ignore(); int i = 0; while(i < rozmiar) { fgets(t, sizeof t, stdin); for (p = t, q = t + sizeof t; p < q; p++) { if (*p >= 48 && *p <= 57) { liczba = *p - 48; calaLiczba = calaLiczba * 10 + liczba; } if (*p == ' ') { a[i][0] = calaLiczba; isY = true; calaLiczba = 0; liczba = 0; } if (*p == '\n') { a[i][1] = calaLiczba; isY = false; } } for (int j = 0; j < 20; j++) t[j] = '\0'; liczba = 0; calaLiczba = 0; isY = false; i++; } cin >> polecenie; cin.ignore(); sort_with_show(a, rozmiar, polecenie); return 0; } 中存在密钥但old中不存在密钥的情况 - 我在此处包含该情况,但如果不相关,您可以删除该代码。您可以类似地处理new中缺少密钥的情况,但我没有那么做。

new

答案 2 :(得分:0)

你可以这样做:

old = [('ver','1121'),('sign','89'),('address','A45'),('type','00')]
new = [('ver','1121'),('sign','89'),('type','01')]
my_list = [(a,b) for (a,b) in new for (c,d) in old  if ((a==c) and (b==d))]
for i in old:
     if i in my_list:
             print "Match : ", i
     else:
             print "Mismatch : ", i

会给你:

Match :  ('ver', '1121')
Match :  ('sign', '89')
Mismatch :  ('address', 'A45')
Mismatch :  ('type', '00')

但可以肯定的是,有更“pythonic”的方式......

答案 3 :(得分:0)

这是一个单行列表,可以获得所有比较的列表。根据您的旧列表和新列表的大小,设置理解会更快一些,但我的sorted + itertools.groupby方法会在sorted返回时取消该速度a list):

comps = [(key, 'changed', old_val, new_val) 
          if old_val != new_val else (key, 'same', old_val)
           for key, old_val in old for oth_key, new_val in new
             if key == oth_key]

comps现在是:

[('ver', 'same', '1121'),
 ('sign', 'same', '89'),
 ('type', 'changed', '00', '01')]

打印出来:

for t in comps:
    if len(t) == 3:
        print('%s: %s, value: %s' % (t[1], t[0], t[2]))
    else:
        print('%s: %s, value: %s' % (t[1], t[0], ', '.join(t[2:])))

same: ver, value: 1121
same: sign, value: 89
changed: type, value: 00, 01

编辑:以下并不是OP想要的,但无论如何我会留下它,对于那些有兴趣看到第一个保持不变的人,以及第二个改变了什么(实际上,你可以定义一个自定义语法来排序你想看到首先改变的元素,但这取决于你。)

准备使用itertools.groupby,并考虑到OP对上面显示的打印指令的请求,我们可以使用collections.OrderedDict对象有效地创建“有序集”的“键”:

import collections

proper_order = tuple(collections.OrderedDict.fromkeys([x[0] for x in new]).keys())

proper_order
Out[43]: ('ver', 'sign', 'type')

现在根据comps中的自定义语法对proper_order进行排序:

comps_sorted = sorted(comps, key=lambda x: proper_order.index(x[0]))

comps_sorted
Out[45]: 
[('ver', 'same', '1121'),
 ('sign', 'same', '89'),
 ('type', 'changed', '00', '01')]

使用itertools.groupby打印:

for key, group in itertools.groupby(comps_sorted, key=lambda x: x[1]):
    for g in group:
        print('%s: %s' % (key, ', '.join(x for x in g if x not in ('same', 'changed'))))

same: ver, 1121
same: sign, 89
changed: type, 00, 01

恰好这个输出的顺序与上面提到的OP相同,但对于更大的情况,两种方法之间的顺序差异将变得明显。

答案 4 :(得分:0)

这个怎么样:

n,o=dict(new),dict(old)
for i in n:
    print "{0:10}:{2:8} {3:8} {1}".format(*(("Match","") if o.get(i)==n[i] else ("Mismatch",o.get(i,i)))+ (i,n[i]))

输出:

Mismatch  :type     01       00
Match     :ver      1121     
Match     :sign     89      

如果您需要订单,请尝试使用OrderedDict

from collections import OrderedDict
n,o=OrderedDict(new),OrderedDict(old)