Using nested dictionaries to store user defined graph
<p>I am trying to get the user to enter a graph manually as opposed to using it 'pre-existing' in the code, for use in my Dijkstra's Algorithm. </p>

<p>I have done this but would like some feedback on its implementation and user friendliness. In addition is there a more efficient way of entering a graph into a nested dictionary ? If so how ?.</p>

<p>Key points about code</p>

<ul>
<li>Data must be stored using nested dictionaries </li>
<li>A loop would be a zero e.g b-b is 0 not left blank, but this only occurs if a loop is present in user graph otherwise its ignored.</li>
<li>Ideally I would not like to use anything inside existing libraries before coding it myself to get a better understanding of what is happening</li>
</ul>

<p>Many Thanks. 
Edit: repeat requirement no longer needed.</p>

<pre><code>{'A': {'C': 1, 'B': 5}, 'D': {}, 'B': {'D': 2}, 'C': {'D': 9}}
</code></pre>

<p>^ Desired output for nodes also current output.</p>

<pre><code>nodes = {}


def add_node():
    entered_graph = False
    while not entered_graph:
        source_node = input("Enter a source node: ")
        num_neighbours = int(input("Enter how many neighbours this node has"
                                   "including previously entered nodes: "))
        nodes[source_node] = {}
        for neighbour in range(num_neighbours):
            neighbour = input("Enter neighbor node: ")
            distance = int(input("Enter distance from source node to this neighbor node: "))
            nodes[source_node][neighbour] = distance
        end_loop = input("Enter y to finish graph entry: ")
        end_loop = end_loop.lower()
        if end_loop == "y":
            entered_graph = True

add_node()
print(nodes)
</code></pre>

<p>You could be more modular in your source, as in "add_node" should only add a node. I think entering all neighbors with costs immediately in one line would be more user friendly, so using the data structure you insist on:</p>

<pre><code>from itertools import tee          #For pairwise iteration
from collection import defaultdict #To add arcs to non-existing nodes

def add_node(graph):
    source = input("Please enter node ('quit' to stop):")
    if node == 'quit': return False
    for neighbor,dist in zip(tee(input("Please enter neighbors [neighbor distance neighbor distance ...]").split())):
        graph[source][neighbor] = int(dist)
        graph[neighbor][source] = int(dist)
    return True

def add_graph(self):
    graph = defaultdict(dict)
    while add_node(graph): pass

print add_graph()
</code></pre>

<p>The defaultdict saves you checking, and I think inputting this way is easier rather than neighbor by neighbor. You could even make this [source neighbor cost neighbor cost ...] - [source ...] - ... for a one line input.</p>

<p>Being modular makes it easier to add code to the 'graph' or to the 'node', if you insist on not making a class out of this.</p>

python dictionary