Find path from a list of tuples in Python

前端 未结 3 458
醉话见心
醉话见心 2021-01-14 21:55

I have a list of tuples of the form:

data = [(\'Abe\', \'Bob\', \'3\'), 
        (\'Abe\', \'Frank\', \'5\'),
        (\'Abe\', \'George\', \'4\'),
        (         


        
相关标签:
3条回答
  • def get_rpath_with_weight(data,start,end):
        rpath = []
        reachable=False
        nxt_dst = start
        weight_ = 0
        rpath.append(nxt_dst)
        for datum in data:
            if nxt_dst in datum:
                #print datum
                fm_ = datum[0]
                to_ = datum[1]
                weight_ = weight_ + int(datum[2])
                if fm_ == nxt_dst:
                   nxt_dst = to_
                else:
                   nxt_dst = fm_
                if nxt_dst == end:
                   reachable=True
                rpath.append(nxt_dst)
        print rpath,weight_,reachable
    
    
    get_rpath_with_weight(data,'Abe','Dan')
    
    get_rpath_with_weight(data,'Dan','Frank')
    

    Sample Output

    ['Abe', 'Bob', 'Carl', 'Dan'] 6 True
    ['Dan', 'Carl'] 2 False
    

    Above example can may get path and determine if reachable, but I think you need to further enhance it to handle multiple paths too.

    0 讨论(0)
  • 2021-01-14 22:42

    You could generate all the possible paths, and sort them by weight. Note I've changed the weights in the data to be numbers, not strings:

    data = [
        ('Abe', 'Bob', 3), 
        ('Abe', 'Frank', 5),
        ('Abe', 'George', 4),
        ('Carl', 'Bob', 1),
        ('Dan', 'Carl', 2),
    ]
    
    WEIGHT = 0
    NODES = slice(1, None)
    
    def get_path_and_weight(data, start, end):
    
        paths = [[0, start]]
        added = True
    
        while added:
            added = False
    
            for first, second, weight in data:
                for path in paths:
                    candidate = None
    
                    if (first in path[NODES]) and (second not in path[NODES]):
                        candidate = second
                    elif (first not in path[NODES]) and (second in path[NODES]):
                        candidate = first
    
                    if candidate:
                        new_path = list(path)
                        new_path.append(candidate)
                        new_path[WEIGHT] += weight
    
                        if new_path not in paths:
                            paths.append(new_path)
                            added = True
    
        for path in sorted(paths):
            if end in path[NODES]:
                return path
    
        return None
    

    You can then call this something like:

    weight, *path = get_path_and_weight(data, "Abe", "Dan")
    
    print(path, "with weight", weight)
    

    Gives the result:

    ['Abe', 'Bob', 'Carl', 'Dan'] with weight 6
    

    And since it returns a path or None, you can still use it as predicate function as well:

    if get_path_and_weight(data, "Abe", "Dan"):
        print("connected")
    
    0 讨论(0)
  • 2021-01-14 22:49

    There are several packages that are already developed and debugged that do this, e.g., networkx

    import networkx as nx
    
    data = [('Abe', 'Bob', '3'), 
            ('Abe', 'Frank', '5'),
            ('Abe', 'George', '4'),
            ('Carl', 'Bob', '1'),
            ('Dan', 'Carl', '2')]
    
    g = nx.Graph()
    for e in data:
        g.add_edge(e[0], e[1], distance=int(e[2]))
    >>> nx.shortest_path(g, 'Abe', 'Bob', 'distance'), nx.shortest_path_length(g, 'Abe', 'Bob', 'distance')
    (['Abe', 'Bob'], 3)
    
    0 讨论(0)
提交回复
热议问题