Python 列表交叉标识
我有4个列表,列表的每个元素是Python 列表交叉标识,python,Python,我有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]
[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])
e两个列表的示例l1 = [ [1,2,'ID123'], [3,4,'ID888'], [2,7, 'ID673'] ]
l2 = [ [3,5,'ID123'], [5,7, 'ID673'],[13,4,'ID456'] ]
tab = [l1, l2]
输出应该是
0 AND 1
-2,-3
-3, 0
如何制作一个包含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)]}
如何制作一个包含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)]}
您可以使用
enumerate
跟踪您所在的位置。此解决方案通过列表理解在第一个列表的第二个列表中查找匹配项。这将贯穿整个列表,但是如果您可以假设每个列表只有一个匹配项,那么您可以在第一次查找时退出搜索并节省时间。但我认为这是一种展示解决方案的信息方式
这为[l1,l2]
和[l1,l2,l1,l2]
等提供了所需的输出。那里的中断条件只是确保我们不会遇到索引器
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])
您可以使用
enumerate
跟踪您所在的位置。此解决方案通过列表理解在第一个列表的第二个列表中查找匹配项。这将贯穿整个列表,但是如果您可以假设每个列表只有一个匹配项,那么您可以在第一次查找时退出搜索并节省时间。但我认为这是一种展示解决方案的信息方式
这为[l1,l2]
和[l1,l2,l1,l2]
等提供了所需的输出。那里的中断条件只是确保我们不会遇到索引器
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])
在
itertools
和操作员的帮助下进行选择
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
按需要导入itertools
从运算符导入itemgetter
从操作员导入子
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]
izip(tab[:-1],tab[1:]):
a、 延长(b)
a、 排序(key=id)
对于键,在其中分组。groupby(a,key=id):
z=贴图(xy,组)
#z=[xy(对象)表示组中的对象]
如果len(z)<2:
持续
(x,y)、(x1,y1)=z
x-=x1
y-=y1
打印键“:”,x,y
#dx,dy=[sub(g,h)表示压缩中的g,h(*z)]
#打印'\t',dx,dyprint'\t',dx,dy
另一种选择,需要itertools
和操作员的帮助
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
按需要导入itertools
从运算符导入itemgetter
从操作员导入子
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]
izip(tab[:-1],tab[1:]):
a、 延长(b)
a、 排序(key=id)
对于键,在其中分组。groupby(a,key=id):
z=贴图(xy,组)
#z=[xy(对象)表示组中的对象]
如果len(z)<2:
持续
(x,y)、(x1,y1)=z
x-=x1
y-=y1
打印键“:”,x,y
#dx,dy=[sub(g,h)表示压缩中的g,h(*z)]
#打印'\t',dx,dyprint'\t',dx,dy
我建议将其实现为一个生成器函数,在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]
我用两对大小不同的列表来计时:
>>> #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)
我建议将其实现为一个生成器函数,它可以在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]
我用两对大小不同的列表来计时:
>>> #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)
您可以使用临时字典来存储在选项卡中的所有列表中具有相同ID的(x,y)对列表。接下来,遍历字典。每个va