Python 列表交叉标识

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]

我有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])
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