Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to merge two sets such that all references to both sets will refer to the new? [closed]

In Python, say I have two sets A and B, along with multiple references to both sets.

Is there a way to merge the two sets A and B such that all references to both sets will refer to the newly merged set? If possible, what will be the runtime?

A = {1,3}
B = {2,4}
aRef1 = A
aRef2 = A
bRef1 = B
bRef2 = B
MergeSets(A,B)
# Now, whenever I use any of (A, B, aRef1, aRef2, bRef1, bRef2) 
# they refer to the same set which will be {1,2,3,4} 

Thank you

EDIT:

Some people have been asking why I wanted to do this, and here's a copy/paste of one of my replies below:

So I know I can do A.update(B), to merge B into A, but then I'd have to iterate through all references to B and set them to refer to A. I was asking so I can avoid these extra iterations. I could supply more context to get a new approach to my specific scenario, but I'm more curious to know if this is possible in python as a general case.

Further, it looks like my question has been answered and the verdict is that this is not possible. Thanks again everybody :)

like image 716
kebab-case Avatar asked Sep 06 '19 15:09

kebab-case


3 Answers

They currently all are referencing to their respective sets A or B, according to the assignments you've made. For instance in the case of bRef1:

id(B)
# 112140097128

id(bRef1)
# 112140097128

The fact that the original set is modified or not by modifying the new sets depends on the kind of operations you perform. If you perform an in-place operation, for instance:

bRef1 |= {5}

And check the original variable B, you can see that indeed it has been updated:

print(B)
# {2, 4, 5}

Though when you merge both sets, unless you also perform an in-place operation and hence explicitly update one of the two sets, you will be creating a new object:

new_set = aRef2 | bRef2

id(new_set)
# 112140098248

But still, in the case you update in-place one of the sets A or B by merging it with the other, given that you've started out with 2 different objects, there is no way of changing that into all sets referencing the same object.

like image 177
yatu Avatar answered Nov 14 '22 22:11

yatu


Given:

A = {1,3}
B = {2,4}
aRef1 = A
aRef2 = A
bRef1 = B
bRef2 = B

if you want all the six objects to refer to the same set but not the same object:

A |= B
B |= A 

print(A, id(A))
print(aRef1, id(aRef1))
print(aRef2, id(aRef2))
print(B, id(B))
print(bRef1, id(bRef1))
print(bRef2, id(bRef2))


#{1, 2, 3, 4} 2668549913736 (1°object)
#{1, 2, 3, 4} 2668549913736 (1°object)
#{1, 2, 3, 4} 2668549913736 (1°object)
#{1, 2, 3, 4} 2668549967944 (2°object)
#{1, 2, 3, 4} 2668549967944 (2°object)
#{1, 2, 3, 4} 2668549967944 (2°object)

if you want all the six objects to refer to the same set but not the same object using mergeList function:

def mergeList(A, B):
    A |= B
    B |= A

mergeList(A, B)
print(A, id(A))
print(aRef1, id(aRef1))
print(aRef2, id(aRef2))
print(B, id(B))
print(bRef1, id(bRef1))
print(bRef2, id(bRef2))


#{1, 2, 3, 4} 2668549913736 (1°object)
#{1, 2, 3, 4} 2668549913736 (1°object)
#{1, 2, 3, 4} 2668549913736 (1°object)
#{1, 2, 3, 4} 2668549967944 (2°object)
#{1, 2, 3, 4} 2668549967944 (2°object)
#{1, 2, 3, 4} 2668549967944 (2°object)

if you want all the six objects to refer to the same set and the same object:

A |= B
B = A
bRef1 = B
bRef2 = B

print(A, id(A))
print(aRef1, id(aRef1))
print(aRef2, id(aRef2))
print(B, id(B))
print(bRef1, id(bRef1))
print(bRef2, id(bRef2))


#{1, 2, 3, 4} 2538372611208 (same object)
#{1, 2, 3, 4} 2538372611208 (same object)
#{1, 2, 3, 4} 2538372611208 (same object)
#{1, 2, 3, 4} 2538372611208 (same object)
#{1, 2, 3, 4} 2538372611208 (same object)
#{1, 2, 3, 4} 2538372611208 (same object)

using mergeList would be a little tricky to have all the variables reference to the same object

like image 42
Nikaido Avatar answered Nov 15 '22 00:11

Nikaido


Python references are passed by value, so you can't reassign bindings passed as parameters to a function. An alternative here would be to mutate the objects passed to your function.

In [35]: A = {1,3}
    ...: B = {2,4}
    ...: aRef1 = A
    ...: aRef2 = A
    ...: bRef1 = B
    ...: bRef2 = B

In [36]: def merge_sets(a, b):
    ...:     for el in b:
    ...:         a.add(el)
    ...:     for el in a:
    ...:         b.add(el)

In [37]: merge_sets(A, B)

In [38]: [id(s) for s in (A, B, aRef1, aRef2, bRef1, bRef2)]
Out[38]:
[140333907731848,
 140333907731176,
 140333907731848,
 140333907731848,
 140333907731176,
 140333907731176]

In [39]: [s for s in (A, B, aRef1, aRef2, bRef1, bRef2)]
Out[39]:
[{1, 2, 3, 4},
 {1, 2, 3, 4},
 {1, 2, 3, 4},
 {1, 2, 3, 4},
 {1, 2, 3, 4},
 {1, 2, 3, 4}]

merge_sets executes in linear time.

like image 21
Jake Romer Avatar answered Nov 14 '22 23:11

Jake Romer