关于python:列表列表,将列表中的第一项与其他列表中的第二个元素相匹配

List of lists, matching first item in a list to second element in the others lists

假设我有这个名单

1
2
3
4
5
A = [['a','b'],
     ['b','c'],
     ['c','a'],
     ['d','a'],
     ['e',None]]

匹配元素的最佳/有效方法是什么,这样您就可以找出在列表中第一个元素和第二个元素之间匹配的列表。

预期匹配项为:

  • 列表2和3匹配0
  • 列表1与列表2匹配
  • 列表0与列表1匹配。

如图所示,一个列表中可以有更多匹配的值,并且不能有任何不匹配的值。列表中还有其他项目,但对于本例来说不需要。每个列表中的第一项和第二项不匹配。每次比赛我都想跑一些东西,我需要一个简单的方法。

这有道理,可行吗?


创建从第一个元素到索引的映射。我假设第一个元素是唯一的,可以简化这个例子:

1
indices = {t[0]: i for i, t in enumerate(A)}

现在,您可以将每个元素琐碎地映射到与其匹配的索引:

1
2
3
for index, (first, second) in enumerate(A):
    if second in indices:
        print(f'Row {index} matches row {indices[second]}')

演示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>>> A = [['a','b'],
...      ['b','c'],
...      ['c','a'],
...      ['d','a'],
...      ['e',None]]
>>> indices = {t[0]: i for i, t in enumerate(A)}
>>> for index, (first, second) in enumerate(A):
...     if second in indices:
...         print(f'Row {index} matches row {indices[second]}')
...
Row 0 matches row 1
Row 1 matches row 2
Row 2 matches row 0
Row 3 matches row 0


你所得到的看起来像是一个图表边缘的列表,你想要找出的是它们是否连接(即它们有一个共同的边缘)。

您也有一个有向图,边的顺序为您的"匹配"计数(这不是您定义的对称)。

1
2
3
4
5
6
7
8
9
10
11
12
13
edge = [['a','b'],
        ['b','c'],
        ['c','a'],
        ['d','a'],
        ['e',None]]

# order of edges doesn't count
def is_connected(e1, e2):
    return e1[0] == e2[1] or e1[1] == e2[0]

# order of edges counts
def is_child(e1, e2):
    return e1[1] == e2[0]

我想你要的是第二张支票

1
2
3
4
5
6
7
8
print(is_connected(edge[0],edge[1]))
print(is_connected(edge[1],edge[2]))
print(is_connected(edge[0],edge[2]))

print(is_child(edge[0],edge[1]))
print(is_child(edge[1],edge[2]))
print(is_child(edge[0],edge[2])) # false
print(is_child(edge[2],edge[0]))

如果要检查图中所有边的这种定向连接,则基本上要按第二个坐标分组,而熊猫中有一个方便的函数groupby,可以执行此操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import pandas as pd
df = pd.DataFrame(edge)

grouped = df.groupby(1)
grouped.groups
# Output:
{'a': [2L, 3L], 'c': [1L], 'b': [0L]}

grouped.groups['a']
# Output:
# [2L, 3L]

grouped[0].apply(lambda x: ','.join(x)).reset_index()
# Output:
#    1    0
# 0  a  c,d
# 1  b    a
# 2  c    b