我有4个列表,列表的每个元素是[x, y, ID]
类型是float,float,string
每个列表中大约有60-70个元素。
如何查找具有相同ID的元素并获取(x1-x2)
和(y1-y2)
?
也许我的代码有更好的方式......
count
= 4(4个列表)
tab
是列表
for i in range(0, count-1):
print i, ' AND ', i+1
for e in tab[i]: # e = [x,y,ID]
for e2 in tab[i+1]:
if e[2] == e2[2]:
print (e[0]-e2[0], e[1]-e2[1])
2个名单的EMAPLE
l1 = [ [1,2,'ID123'], [3,4,'ID888'], [2,7, 'ID673'] ]
l2 = [ [3,5,'ID123'], [5,7, 'ID673'],[13,4,'ID456'] ]
tab = [l1, l2]
OUTPUT应为
0 AND 1
-2,-3
-3, 0
答案 0 :(得分:2)
如何制作4个列表的ID字典,每个字典元素将是(ID,包含此ID的列表的编号)。填写字典后,您只需翻阅字典并打印出具有多个值关联的ID。
编辑:添加代码示例
l1 = [ [1,2,'ID123'], [3,4,'ID888'], [2,7, 'ID673'] ]
l2 = [ [3,5,'ID123'], [5,7, 'ID673'],[13,4,'ID456'] ]
tab = [l1, l2]
count = len(tab)
dic = {}
for i in range(0, count):
for e in range(0, len(tab[i])):
if not (tab[i][e][2] in dic):
dic[tab[i][e][2]] = []
dic[tab[i][e][2]].append((i, e))
print dic
结果字典将是:
{'ID888': [(0, 1)], 'ID673': [(0, 2), (1, 1)], 'ID123': [(0, 0), (1, 0)], 'ID456': [(1, 2)]}
答案 1 :(得分:1)
您可以使用enumerate
来跟踪自己的位置。此解决方案在此处查找第一个通过列表解析的第二个列表中的匹配项。这将遍历整个列表,但如果您可以假设每个列表只有一个匹配项,则可以在首次查找时退出搜索并节省时间。但我认为这是展示解决方案的信息方式。
这为[l1,l2]
和[l1,l2,l1,l2]
等提供了所需的输出。那里的中断条件只是确保我们不会遇到IndexErrors。
def checkl(tab):
for i,sublist in enumerate(tab):
for elm in tab[i]:
elmid = elm[2]
for el in [x for x in tab[i+1] if x[2] == elmid]:
print elm[0]-el[0],elm[1]-el[1]
if (i+2) == len(tab):
break
if __name__ == '__main__':
checkl([l1,l2])
答案 2 :(得分:1)
我建议将它实现为生成器函数,在具有相同ID的数字之间产生(dx,dy)对差异。为了比较不同的实现,我进行了一些时间安排。 第一个函数使用嵌套for循环表示您的实现:
def f(l1, l2):
"""
Nested for loops
"""
for e in l1:
for e2 in l2:
if e[2] == e2[2]:
yield (e[0]-e2[0], e[1]-e2[1])
第二个迭代列表的排序串联,如果它们的ID相等,则产生相邻对之间的差异。这应该与排序+线性一样快:
def f1(l1, l2):
"""
Iterate over the sorted concatenation
"""
l3 = sorted(l1+l2, key = lambda x: x[2]) #concatenate and then sort by ID
N = len(l3)
for i in range(N - 1):
if l3[i][2] == l3[i+1][2]:
yield (l3[i][0]-l3[i+1][0], l3[i][1]-l3[i+1][1]
我用2对不同大小的列表计时:
>>> #small lists
... l1 = [ [1,2,'ID123'], [3,4,'ID888'], [2,7, 'ID673'] ]
>>> l2 = [ [3,5,'ID123'], [5,7, 'ID673'],[13,4,'ID456'] ]
>>>
>>> #large lists (10k items)
... l3 = [[1,2, 'ID'+str(x)] for x in range(10000)]
>>> l4 = [[1,2, 'ID'+str(x)] for x in range(7000,17000)]
>>> assert list(f(l1,l2)) == list(f1(l1,l2))
>>> assert list(f(l3,l4)) == list(f1(l3,l4))
因此,对于小型列表,第一个功能更快
>>> timeit.timeit("for dx, dy in f(l1,l2): pass", setup="from __main__ import f,l1,l2", number=10000)
0.07620218006741197
>>> timeit.timeit("for dx, dy in f1(l1,l2): pass", setup="from __main__ import f1,l1,l2", number=10000)
0.2245986360430834
但是对于大型列表,第二个更快
>>> timeit.timeit("for dx, dy in f(l3,l4): pass", setup="from __main__ import f,l3,l4", number=1)
37.525589103028324
>>> timeit.timeit("for dx, dy in f1(l3,l4): pass", setup="from __main__ import f1,l3,l4", number=1)
0.04416877092444338
基于此,我们可以得出结论,在小型列表的情况下,您的实现是正常的,因为它非常简单,并且可以说比其他人更难以实现。如果您需要处理大型列表,第二种算法会更快,但要注意两次内存使用情况。要获得dx和dy以供进一步使用,您可以简单地遍历生成器:
tab = [l1, l2]
for dx, dy in f1(*tab):
print(dx, dy)
答案 3 :(得分:0)
替代itertools
和operator
import itertools as it
from operator import itemgetter
from operator import sub
id = itemgetter(2)
xy = itemgetter(0,1)
l1 = [ [1,2,'ID123'], [3,4,'ID888'], [2,7, 'ID673'] ]
l2 = [ [3,5,'ID123'], [5,7, 'ID673'],[13,4,'ID456'] ]
tab = [l1, l2]
for a,b in it.izip(tab[:-1], tab[1:]):
a.extend(b)
a.sort(key=id)
for key, group in it.groupby(a, key = id):
z = map(xy, group)
#z = [xy(thing) for thing in group]
if len(z) < 2:
continue
(x, y), (x1, y1) = z
x -= x1
y -= y1
print key, ':', x, y
#dx, dy = [sub(g, h) for g, h in zip(*z)]
#print '\t', dx, dyprint '\t', dx, dy
答案 4 :(得分:0)
您可以使用临时字典存储选项卡中所有列表中具有相同ID的(x,y)对列表。接下来,遍历字典。每个值都是(x,y)对的列表。您只需要找到此列表中所有对之间的差异。对字典中的所有值重复它会给你你想要的东西。
l1 = [ [1,2,'ID123'], [3,4,'ID888'], [2,7, 'ID673'] ]
l2 = [ [3,5,'ID123'], [5,7, 'ID673'],[13,4,'ID456'] ]
tab = [l1, l2]
dict1 = {}
for l in tab:
for (x, y, z) in l:
dict1.setdefault(z, []).append((x, y))
for (k, v) in dict1.items():
for i in range(0, len(v)):
for j in range(i+1, len(v)):
xdiff = v[i][0] - v[j][0]
ydiff = v[i][1] - v[j][1]
print '%d, %d' % (xdiff, ydiff)