我的数据格式为:
lsta = [[0,1], [0,2], [1,3], [2,4], [3,5], [4,6], [5,7], [7,9], [8,10], [8,11], [10,12], [11,13], [11,14], [12,15], [12,16], [6,17], [8,17]]
我正在尝试根据数据是否已连接将数据拆分为两个列表,因此我猜您可以将数据视为图表。
目前,我有一个递归函数,它将按顺序跟踪数据[0,1]
- > [1,3]
- > [3,5]
等。
但是,当编号没有按顺序排列时会出现故障;例如,连接6,17和8但是由于原始数据的格式化,这将被分成多个列表。我对此的预期解决方案是在序列的以下用完之后执行检查,以查看是否在字典中的任何其他位置(而不仅仅是键)找到该值,如果是,则该函数将从该点继续跟随。不幸的是,我无法让它工作,建议赞赏。
下面的当前代码,'check'功能目前是没有按预期执行的位。
from collections import defaultdict
def split(items):
# create lookup
lookup = defaultdict(set)
for k, v in items:
lookup[k].add(v)
results = []
while sum(map(len, lookup.values())):
# get first element from remaining items
first_k = min((k for k in lookup if len(lookup[k])))
first = first_k, min(lookup[first_k])
# follow that element
results.append(follow(first, lookup))
return results
def follow(item, lookup):
item_k, item_v = item
lookup[item_k].remove(item_v)
result = [item]
# loop through all follow-up items (if any)
for next_item in sorted(lookup[item_v]):
# recursively follow the follow-up item
result.extend(follow((item_v, next_item), lookup))
try:
#check if v appears in v of another key
result.extend(check((item_v, next_item), lookup))
except KeyError:
break
return result
def check(item, lookup):
itm_k, itm_v = item
rsult = []
if itm_v in lookup.values():
#if it appears again, follow item
rsult.extend(follow((itm_k, next_item), lookup))
return rsult
def test(items):
for x in split(items):
print(x)
lsta = [
[ 0, 1], [ 0, 2], [ 1, 3], [ 2, 4],
[ 3, 5], [ 4, 6], [ 5, 7], [ 7, 9],
[ 8, 10], [ 8, 11], [10, 12], [11, 13],
[11, 14], [12, 15], [12, 16], [ 6, 17],
[ 8, 17],
]
test(lsta)
所需的输出将是:
results = ([[0,1], [1,3], [3,5], [5,7], [7,9]], [[0,2], [2,4], [4,6], [6,17], [8,17], [8,10], [8,11], [11,13], [11,14], [10,12], [12,15], [12,16]])
答案 0 :(得分:1)
我建议你退后一步,以不同的方式思考你的问题。根据您的问题,您试图在lsta
对列表中识别连接的子图。根据你的说法,这些图表简单地连接 - 也就是说,(a,b)与(b,a)相同,没有定向性感。
查看前两对,您有0,1
和0,2
。这会产生一个由{0,1,2}
组成的子图,因为你并不关心哪一端是常见的。 set
类型将是您解决方案的关键。而不是担心递归,尝试管理集合以获得您想要的结果。
首先,导入集合然后创建默认字典。你不需要直接导入defaultdict,因为你只需要输入一次,这样可以清理一下:
import collections
Subgraphs = collections.defaultdict(set)
现在让我们添加您的初始测试数据。 请注意:有一个'错误'在这里,最后一对(8,17)将子图连在一起。你可能不想要那个。
lsta = [
[ 0, 1], [ 0, 2], [ 1, 3], [ 2, 4],
[ 3, 5], [ 4, 6], [ 5, 7], [ 7, 9],
[ 8, 10], [ 8, 11], [10, 12], [11, 13],
[11, 14], [12, 15], [12, 16], [ 6, 17],
[ 8, 17],
]
现在让我们初始化集合。每个节点(整数)将指向它所连接的集合。最初,节点仅与自身连接,因此每个键K
将指向一组{K}
。
for a,b in lsta:
Subgraphs[a].add(a)
Subgraphs[b].add(b)
现在让我们合并这些集合。每对(a,b)
表示a
和b
已关联。这意味着这两个节点应共享相同的节点集,因为它们(通过彼此)连接到所有邻居的并集。
我们假设节点A指向一个集合,该集合中的所有节点也指向同一个集合。 (这是一些Python技巧。他们不是副本同一组,但实际引用到内存中的相同对象。)这意味着更新该集合可以只进行一次,它将影响所有成员。
for a,b in lsta:
seta = Subgraphs[a]
setb = Subgraphs[b]
others = setb - seta
seta |= setb
print("Processing (%d, %d): %s" % (a, b, seta))
print("... updating: ", others)
for o in others:
Subgraphs[o] = seta
此时,Subgraphs
字典中的所有键(节点)都应指向包含所有可到达邻居的集合。我们将打印输入和结果数据,然后让您进入。
print("\n***********")
print(lsta)
print(Subgraphs)
您可能想删除最后一对:[8,17]。此外,您可能希望识别唯一的子图。我不知道你对这段代码做了什么,但是如果你真的需要子图,你可以将它们变成frozenset
个对象,然后可以将它们添加到set
制作一个独特的集合。或者,您可以迭代Subgraphs
dict的键,将集合合并到seen
集合并跳过seen
中已有的任何键。
以下是我使用lsta
数据运行时得到的输出:
Processing (0, 1): {0, 1}
... updating: {1}
Processing (0, 2): {0, 1, 2}
... updating: {2}
Processing (1, 3): {0, 1, 2, 3}
... updating: {3}
Processing (2, 4): {0, 1, 2, 3, 4}
... updating: {4}
Processing (3, 5): {0, 1, 2, 3, 4, 5}
... updating: {5}
Processing (4, 6): {0, 1, 2, 3, 4, 5, 6}
... updating: {6}
Processing (5, 7): {0, 1, 2, 3, 4, 5, 6, 7}
... updating: {7}
Processing (7, 9): {0, 1, 2, 3, 4, 5, 6, 7, 9}
... updating: {9}
Processing (8, 10): {8, 10}
... updating: {10}
Processing (8, 11): {8, 10, 11}
... updating: {11}
Processing (10, 12): {8, 10, 11, 12}
... updating: {12}
Processing (11, 13): {8, 10, 11, 12, 13}
... updating: {13}
Processing (11, 14): {8, 10, 11, 12, 13, 14}
... updating: {14}
Processing (12, 15): {8, 10, 11, 12, 13, 14, 15}
... updating: {15}
Processing (12, 16): {16, 8, 10, 11, 12, 13, 14, 15}
... updating: {16}
Processing (6, 17): {0, 1, 2, 3, 4, 5, 6, 7, 17, 9}
... updating: {17}
Processing (8, 17): {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}
... updating: {0, 1, 2, 3, 4, 5, 6, 7, 9, 17}
*********
LSTA: [[0, 1], [0, 2], [1, 3], [2, 4], [3, 5], [4, 6], [5, 7], [7, 9], [8, 10], [8, 11], [10, 12], [11, 13], [11, 14], [12, 15], [12, 16], [6, 17], [8, 17]]
Subgraphs: defaultdict(<class 'set'>, {0: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 1: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 2: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 3: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 4: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 5: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 6: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 7: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 8: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 9: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 10: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 11: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 12: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 13: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 14: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 15: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 16: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}, 17: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17}})
以下是我从lsta
删除[8,17]对时的结果:
Processing (0, 1): {0, 1}
... updating: {1}
Processing (0, 2): {0, 1, 2}
... updating: {2}
Processing (1, 3): {0, 1, 2, 3}
... updating: {3}
Processing (2, 4): {0, 1, 2, 3, 4}
... updating: {4}
Processing (3, 5): {0, 1, 2, 3, 4, 5}
... updating: {5}
Processing (4, 6): {0, 1, 2, 3, 4, 5, 6}
... updating: {6}
Processing (5, 7): {0, 1, 2, 3, 4, 5, 6, 7}
... updating: {7}
Processing (7, 9): {0, 1, 2, 3, 4, 5, 6, 7, 9}
... updating: {9}
Processing (8, 10): {8, 10}
... updating: {10}
Processing (8, 11): {8, 10, 11}
... updating: {11}
Processing (10, 12): {8, 10, 11, 12}
... updating: {12}
Processing (11, 13): {8, 10, 11, 12, 13}
... updating: {13}
Processing (11, 14): {8, 10, 11, 12, 13, 14}
... updating: {14}
Processing (12, 15): {8, 10, 11, 12, 13, 14, 15}
... updating: {15}
Processing (12, 16): {16, 8, 10, 11, 12, 13, 14, 15}
... updating: {16}
Processing (6, 17): {0, 1, 2, 3, 4, 5, 6, 7, 17, 9}
... updating: {17}
*********
LSTA: [[0, 1], [0, 2], [1, 3], [2, 4], [3, 5], [4, 6], [5, 7], [7, 9], [8, 10], [8, 11], [10, 12], [11, 13], [11, 14], [12, 15], [12, 16], [6, 17]]
Subgraphs: defaultdict(<class 'set'>, {0: {0, 1, 2, 3, 4, 5, 6, 7, 17, 9}, 1: {0, 1, 2, 3, 4, 5, 6, 7, 17, 9}, 2: {0, 1, 2, 3, 4, 5, 6, 7, 17, 9}, 3: {0, 1, 2, 3, 4, 5, 6, 7, 17, 9}, 4: {0, 1, 2, 3, 4, 5, 6, 7, 17, 9}, 5: {0, 1, 2, 3, 4, 5, 6, 7, 17, 9}, 6: {0, 1, 2, 3, 4, 5, 6, 7, 17, 9}, 7: {0, 1, 2, 3, 4, 5, 6, 7, 17, 9}, 8: {16, 8, 10, 11, 12, 13, 14, 15}, 9: {0, 1, 2, 3, 4, 5, 6, 7, 17, 9}, 10: {16, 8, 10, 11, 12, 13, 14, 15}, 11: {16, 8, 10, 11, 12, 13, 14, 15}, 12: {16, 8, 10, 11, 12, 13, 14, 15}, 13: {16, 8, 10, 11, 12, 13, 14, 15}, 14: {16, 8, 10, 11, 12, 13, 14, 15}, 15: {16, 8, 10, 11, 12, 13, 14, 15}, 16: {16, 8, 10, 11, 12, 13, 14, 15}, 17: {0, 1, 2, 3, 4, 5, 6, 7, 17, 9}})