【问题标题】:Python: Finding a path between nodes within groups with nested dictionariesPython:使用嵌套字典查找组内节点之间的路径
【发布时间】:2015-10-27 06:41:44
【问题描述】:

我有一个包含房地产历史交易记录的数据集。每个属性都有一个 ID 号。为了检查数据是否完整,我为每个房产确定了一个“交易链”:我选择最初的买家,并遍历所有中间买家/卖家组合,直到我到达最终的记录买家。所以对于看起来像这样的数据:

买家|卖家|propertyID 鲍勃|简|23 蒂姆|鲍勃|23 卡尔|蒂姆|23

交易链看起来像:[Jane, Bob, Tim, Karl]

我正在使用三个数据集来执行此操作。第一个包含每个房产的第一个买家的姓名。第二个包含所有中间买家和卖家的姓名,第三个仅包含每个房产的最终买家。我使用三个数据集,所以我可以按照vikramls answer here 给出的过程。

在我的图字典版本中,每个卖家都是对应买家的键,经常引用的 find_path 函数查找从第一个卖家到最后一个买家的路径。问题是数据集非常大,所以我得到了最大递归深度达到错误。我想我可以通过将图形字典嵌套在另一个字典中来解决这个问题,其中它们的键是属性 ID 号,然后在 ID 组中搜索路径。但是,当我尝试时:

graph = {}
propertyIDgraph = {}

with open('buyersAndSellers.txt','r') as f:
    for row in f:
        propertyid, seller, buyer = row.strip('\n').split('|')
        graph.setdefault(seller, []).append(buyer)
        propertyIDgraph.setdefault(propertyid, []).append(graph)
f.close()

它将每个买家/卖家组合分配给每个属性 ID。我希望它只为买家和卖家分配相应的房产 ID。

【问题讨论】:

  • 您是想专门用字典来做这件事,还是对图书馆开放?我会指出,鉴于购买/销售中的电路,您当前的方法将失败,也许您的业务领域不允许这样做。
  • 我对图书馆开放。我使用字典是因为它是我在 python 中研究节点之间的路径时发现的第一件事
  • 您可能在模型的某处有一个电路(如前所述)......例如卡尔卖给简,简卖给鲍勃,鲍勃卖给蒂姆,蒂姆又卖给简,简卖给里克。当你到达 Jane 时,你不知道是走到 Bob 还是 Rick,所以如果你选择 Bob,你将永远继续绕着一圈走。在完全不了解您的代码的情况下,这将是首先要检查的事情。图表可能不是一个好的选择;最好只添加一个列表,即 defaultdict(list) 可能是一个更好的模型。
  • 是的,电路确实存在。所以我可以使用 defaultdict(list) 来创建字典,但是 find_path 函数会像当前编写的那样工作吗?换句话说,唯一需要改变的是图结构?

标签: python for-loop dictionary iteration hierarchy


【解决方案1】:

您可能会尝试以下操作。我改编自https://www.python.org/doc/essays/graphs/的链接

Transaction = namedtuple('Transaction', ['Buyer', 'PropertyId'])

graph = {}
## maybe this is a db or a file
for data in datasource:
    graph[data.seller] = Transaction(data.buyer,data.property_id)

## returns something like
## graph = {'Jane': [Transaction('Bob',23)],
##        'Bob': [Transaction('Tim',23)],
##        'Time': [Transaction('Karl',23)]}
##

def find_transaction_path(graph,  original_seller,current_owner,target_property_id path=[]):
    assert(target_property_id is not None)

    path = path + [original_seller]
    if start == end:
        return path
    if not graph.has_key(original_seller):
        return None
    shortest = None
    for node in graph[start]:
        if node not in path and node.property_id == target_property_id:
            newpath = find_shortest_path(graph, node.Buyer, current_owner, path,target_property_id)
            if newpath:
                if not shortest or len(newpath) < len(shortest):
                    shortest = newpath
    return shortest

【讨论】:

  • 您能否扩展一下如何在不进行硬编码的情况下将列中的信息转换为命名元组和图形格式?另外,我没有看到函数中的propertyID在哪里使用,即函数在哪里说只在ID组内迭代?
【解决方案2】:

我不建议附加到图表。它将附加到每个节点。最好先检查是否存在,而不是将其附加到已存在的对象后。

试试这个:

graph = {}
propertyIDgraph = {}

with open('buyersAndSellers.txt','r') as f:
    for row in f:
        propertyid, seller, buyer = row.strip('\n').split('|')
        if seller in graph.iterkeys() :
            graph[seller] = graph[seller] + [buyer]
        else:
            graph[seller] = [buyer]
        if propertyid in propertyIDgraph.iterkeys():
            propertyIDgraph[propertyid] = propertyIDgraph[propertyid] + [graph]
        else:
            propertyIDgraph[propertyid] = [graph]
f.close()

这里有一个可能有用的链接:

syntax for creating a dictionary into another dictionary in python

【讨论】:

  • 感谢您的回复。我使用的是 python 3,所以我将 .iterkeys() 更改为 .items(),但使用此方法仍会在每个属性 ID 中包含每个买卖双方对。
  • 我认为在python3中iterkeys()只是keys()。在 python 2 中工作正常,对不起,但我不知道 python3。
猜你喜欢
  • 1970-01-01
  • 2021-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-06
  • 1970-01-01
  • 1970-01-01
  • 2012-12-15
相关资源
最近更新 更多