【问题标题】:Find all tuples related to a certain string in Python在 Python 中查找与某个字符串相关的所有元组
【发布时间】:2019-11-28 02:56:37
【问题描述】:

我正在尝试查找与字符串相关的所有元组,而不仅仅是与之匹配。 这是我做的:

from itertools import chain

data = [('A','B'),('B','C'),('B','D'),('B','F'),('F','W'),('W','H'),('G','Z')]
init = 'A'

filtered_init = [item for item in data if item[0] == init or item[1] == init]
elements = list(dict.fromkeys([ i for i in chain(*filtered_init)]))
elements.remove(init)

dat = []
for i in elements:
    sync = [item for item in data if item[0] == i or item[1] == i]
    dat.append(sync)

print(dat)

结果是:

[('A', 'B'), ('B', 'C'), ('B', 'D'), ('B', 'F')]

但是,它只包含 A-B 相关的级别。 我要查找的是与init 字符串相关的所有元组,如下图所示:

换句话说,[('A','B'),('B','C'),('B','D'),('B','F'),('F','W'),('W','H')] 它是找到所有可以到达init 的边。 我怎样才能得到它们?

【问题讨论】:

  • 你的意思是,这是一个有向图(或者可能是一棵树),并且你想找到从A 到达的所有边?
  • 是的!我想我应该澄清一下帖子。谢谢你的提问:)
  • 你只想跟随(from, to)方向的边,还是无向图?
  • 只是元组格式的边缘 :)
  • 我的意思是,例如,如果有一个元组('Z', 'H'),那会使'Z' 也与'A' 相关,还是因为顺序错误而不算数?

标签: python graph-theory graph-algorithm


【解决方案1】:

您的问题是在由edge list data structure 定义的无向图中找到initconnected component

这个数据结构对于这个问题用起来不是很方便,所以第一步是把它转换成adjacency list。从那里,我们可以应用任何标准的graph traversal 算法,例如depth first search。完成后,我们可以将结果转换回您想要输出的边缘列表格式。

from collections import defaultdict

def find_connected_component(edge_list, start):
    # convert to adjacency list
    edges = defaultdict(list)
    for a, b in edge_list:
        edges[a].append(b)
        edges[b].append(a)

    # depth-first search
    stack = [start]
    seen = set()

    while stack:
        node = stack.pop()
        if node not in seen:
            seen.add(node)
            stack.extend(edges[node])

    # convert back to edge list
    return [ edge for edge in edge_list if edge[0] in seen ]

用法:

>>> find_connected_component(data, init)
[('A', 'B'), ('B', 'C'), ('B', 'D'), ('B', 'F'), ('F', 'W'), ('W', 'H')]

【讨论】:

  • 现在,我只是想知道如何处理如果有一个元组('Z','H'),它不会计数,这意味着顺序很重要。你也能解释一下吗?
  • 只需删除edges[b].append(a)这一行。那条线插入一条“反方向”的边,使图形无向;如果你把它拿出来,那么你就有一个有向图。
【解决方案2】:

为了提高效率,您可以使用DSU。此解决方案有效 O(N)

from functools import reduce
import random

parent = dict()
init = 'A'
data = [('A','B'),('B','C'),('B','D'),('B','F'),('F','W'),('W','H'),('G','Z')]

def make_set(v):
    parent[v] = v

def find_set(v):
    if v == parent[v]:
        return v
    parent[v] = find_set(parent[v])
    return parent[v]

def union_sets(a, b):
    a, b = map(find_set, [a, b])
    if a != b:
        if random.randint(0, 1):
            a, b = b, a
        parent[b] = a;

elements = set(reduce(lambda x, y: x+y, data))

for v in elements:
    parent[v] = v

for u, v in data:
    union_sets(u, v)

init_set = find_set(init)
edges_in_answer = [e for e in data if find_set(e[0]) == init_set]
print(edges_in_answer)

输出:[('A', 'B'), ('B', 'C'), ('B', 'D'), ('B', 'F'), ( 'F', 'W'), ('W', 'H')]

【讨论】:

  • 你确定这样更有效率吗?根据我的基准,这个解决方案比 DFS 慢大约 3 倍。渐近地,DFS 是 O(n),但这实际上略高于 O(n),因为不相交集数据结构的操作并不是 O(1)。
  • 顺便说一句,使用reduce将元组连接在一起是O(n^2);最好使用set(itertools.chain.from_iterable(data))
  • 可能,是的。我假设这段代码的瓶颈是将字符串存储在parent 中。这并不完全正确。但是,dsu 渐近优于 dfs,不是吗?
  • 不,在具有 m 个顶点和 n 个边的图上,DFS 是 O(m + n)。在这个问题中,只提供了边列表,所以顶点的数量严格来说最多是边的数量,因此 DFS 是 O(n)。相比之下,您的算法执行 O(n) DSU 操作,因此其复杂度为 O(n alpha n),其中 alpha 是反阿克曼函数。这比 O(n) 略多,出于实际目的,我们可以称之为 O(n),但这只是渐近地等于 DFS。请参阅cis.upenn.edu/~sanjeev/papers/soda14_disjoint_set_union.pdf 以分析随机链接的数据结构。
【解决方案3】:

一个非常幼稚的解决方案,对于复杂的树可能效率不高。

data = [('A', 'B'), ('B', 'C'), ('B', 'D'), ('B', 'F'),
        ('F', 'W'), ('W', 'H'), ('G', 'Z')]
init = ['A']
result = []
while init:
    initNEW = init.copy()
    init = []
    new = 0
    for edge in data:
        for vertex in initNEW:
            if edge[0] == vertex:
                result.append(edge)
                init.append(edge[1])
                new += 1
    for i in range(len(result) - new, len(result)):
        data.remove(result[i])
print(result)
# [('A', 'B'), ('B', 'C'), ('B', 'D'), ('B', 'F'), ('F', 'W'), ('W', 'H')]

【讨论】:

    猜你喜欢
    • 2016-12-17
    • 2022-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-15
    • 1970-01-01
    • 1970-01-01
    • 2014-07-10
    相关资源
    最近更新 更多