Shared code block followed by different block for mutually exclusive predicates

What is the best way to express this code? (It was difficult to phrase in words) if cond1 or cond2: # shared code if cond1: # cond1 code else: # cond2 code The above obviously duplicates the check if cond1: # shared # cond1 elif cond2: # shared # cond2 This repeats the shared code I am writing an implementation of Dijkstra's, the question arises within the relax function def dijkstra(s): def relax(w, v, edge_cost): w_via_v = distance[v] + edge_cost if w not in distance: distance[w] = w_via_v toexplore.push(w) elif w_via_v < distance[w]: distance[w] = w_via_v toexplore.update(w) distance = {s: 0} toexplore = PriorityQueue([s], sortkey=lambda v: distance[v]) while not toexplore.is_empty(): v = toexplore.popmin() # Assert: v.distance is distance(s to v) # Assert: thus, v is never put back into toexplore for w, edge_cost in v.neighbours: relax(w, v, edge_cost) Another alternative is def relax(w, v, edge_cost): if w not in distance: distance[w] = ∞ toexplore.push(w) w_via_v = distance[v] + edge_cost if w_via_v < distance[w]: distance[w] = w_via_v toexplore.update(w) But this unnecessarily pushes a node into the priority queue only to update it again

Jan 26, 2025 - 17:24
 0
Shared code block followed by different block for mutually exclusive predicates

What is the best way to express this code? (It was difficult to phrase in words)

if cond1 or cond2:
    # shared code
    if cond1:
        # cond1 code
    else:
        # cond2 code

The above obviously duplicates the check

if cond1:
    # shared
    # cond1
elif cond2:
    # shared
    # cond2

This repeats the shared code

I am writing an implementation of Dijkstra's, the question arises within the relax function

def dijkstra(s):
    
    def relax(w, v, edge_cost):
        w_via_v = distance[v] + edge_cost
        if w not in distance:
            distance[w] = w_via_v
            toexplore.push(w)
        elif w_via_v < distance[w]:
            distance[w] = w_via_v
            toexplore.update(w)
    
    distance = {s: 0}
    toexplore = PriorityQueue([s], sortkey=lambda v: distance[v])
    
    while not toexplore.is_empty():
        v = toexplore.popmin()
        # Assert: v.distance is distance(s to v)
        # Assert: thus, v is never put back into toexplore
        for w, edge_cost in v.neighbours:
            relax(w, v, edge_cost)

Another alternative is

def relax(w, v, edge_cost):
    if w not in distance:
        distance[w] = ∞
        toexplore.push(w)
    w_via_v = distance[v] + edge_cost
    if w_via_v < distance[w]:
        distance[w] = w_via_v
        toexplore.update(w)

But this unnecessarily pushes a node into the priority queue only to update it again