Merge pairs on common integer with restrictions

Merge pairs on common integer with restrictions



I need an efficient way to merge a list of nodes (pairs of integers).

The merge should happen only if there is one common number in the pair and the common number is on the first or the last position (otherwise its allready connected).



For example:


mylist = [[4, 3], [6, 3]]
merge_links(mylist) # should output [4, 3, 6]



another example:


mylist = [[4, 3], [6, 3], [6, 4]]
merge_links(mylist)
# should output again [4, 3, 6] because both 6 and 4 allready exist in array.



and yet another example:


mylist = [[4, 3], [6, 3], [6, 4], [6, 2], [7, 4], [4, 9]]
merge_links(mylist)
# should output [7, 4, 3, 6, 2]




# [4, 3] ✔
# [4, 3] + [6, 3] ✔ -> [4, 3, 6]
# [4, 3, 6] + [6, 3] ✘ both 6 and 3 exist in [4, 3, 6]
# [4, 3, 6] + [6, 4] ✘ both 6 and 4 exist in [4, 3, 6]
# [4, 3, 6] + [6, 2] ✔ -> [4, 3, 6, 2]
# [4, 3, 6, 2] + [7, 4] ✔ -> [7, 4, 3, 6, 2]
# [7, 4, 3, 6, 2] + [4, 9] ✘ 4 is allready connected "7-4-3"!



Currently I'm using:


def merge_links(a, b):
inter = np.intersect1d(a, b, True)
a = set(a) - set(inter)
b = set(b) - set(inter)
n = np.unique(list(a) + list(inter) + list(b))
return n



But it doesnt work well for the above restrictions





This appears to be a graph traversal problem, with the pairs as edges. Would using the graph package help you?
– Prune
Aug 28 at 18:17


graph





It is actually a graph I'm trying to create. graph package is most welcome
– Panos Kal.
Aug 28 at 18:18





Is every input pair guaranteed to have 2 different numbers (no pair would be [a, a])?
– Mohamed EL Tair
Aug 28 at 19:03





Also is merging order dependent or not? For example if your list is [ [1, 2], [3, 4], [2, 3] ], should the output be [1, 2, 3] or [1, 2, 3, 4]?
– Mohamed EL Tair
Aug 28 at 19:09





It is order depend. The output would be [1,2,3] having rejected the second pair [3,4] but an unordered solution is welcomed
– Panos Kal.
Aug 28 at 19:11





1 Answer
1



The code below works as follows:



Note: every merging operation takes O(1). Also you can use an array of booleans instead of dictionary if you know the range of pairs values.


#The function takes a list of pairs as an argument
def merge_lst(lst):

#Dictionary to check if value is already in array
visited = dict()

#Length of old list
lst_len = len(lst)

#New list will have at most lst_len+1 elements
new_lst = [0]*(lst_len+1)

#Put the first pair values in last and first elements of the new list repectively and mark them as visited
new_lst[lst_len], new_lst[0] = lst[0][0], lst[0][1]
visited[lst[0][0]], visited[lst[0][1]] = True, True

#Maintain the positions of your first and last elements, which are the the last index and 0 respectively now
first_index, last_index = lst_len, 0

#Iterate on the rest of pairs
for i in range(1, lst_len):

#Check if pair[a, b] are already visited
a_exists, b_exists = lst[i][0] in visited, lst[i][1] in visited

#Skip if they both exist or don't exist
if(a_exists == b_exists):
continue

#Assume a was the common one
common, to_merge = lst[i][0], lst[i][1]

#If b exists (b is the common not a), then just swap
if(b_exists):
common, to_merge = lst[i][1], lst[i][0]

#If the common element is at the first index, the first element and index are updated
if(new_lst[first_index] == common):
first_index-=1
new_lst[first_index] = to_merge
visited[to_merge] = True

#If the common element is at the last index, the last element and index are updated
elif(new_lst[last_index] == common):
last_index+=1
new_lst[last_index] = to_merge
visited[to_merge] = True

#Else, the common element is somewhre in the middle (already connected)

#Return concatenation of new_lst[first_index to the end] with new_lst[0 to the last_index]
return new_lst[first_index:lst_len+1]+new_lst[0:last_index+1]



This code gives correct output for all of your mentioned test cases.






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)