List of tuple like independent data access
Question: I have some paired objects linked together in a same level priority basis.
They can be grouped as fixed length tuples, all have to be in a list. Some
objects type are unique, other can be common). For example, in this data
structure i have an object, an object name (both unique), an object type and a
bool (both common).

    
    
    [(Banana, myBanana, fruit, True),
    (Water, myWater, liquid, True),
    (Car, myCar, vehicle, False)]
    

Then I need to find an easy way to access to the other data knowing the unique
objects. If I pick up "Banana" I'd get (myBanana, fruit, True), if I pick
"myCar" I get (Car, vehicle, False). I don't need to access by the common
values, they're just there to show that the data structure can have common
values and they might change. The order might not be important, I used a list
for simplicity.

Obviously, I can create 2 dictionaries using one of the unique objects each as
keys, but I could actually have a more complex situation with more unique
objects types and some related data (e.g. the last bool) might change, which
would force me to change all the other dictionaries. One idea could be create
a class which contains separate lists for each data type, use index() for a
selected "column" and return a tuple of the other list[index] values. Is there
a better/faster/nicer/more elegant and pythonic way to do this?


Answer: I tried the solution in making a class. It does work and I believe it's fairly
pythonic. It uses two dicts: one where each unique is a key for the commons
and one dict containing the keys. Since no one has given an answer I thought I
might as well share it.

    
    
    class Foo(object):  # Didn't know how to name it.
    
        def __init__(self):
            self.value = dict()
            self.key = dict()
    
        def add(self, keys, values):
            for key in keys:
                self.value[key] = values  # Each key reference the values.
                self.key[key] = keys  # Each key reference to all the keys that reference the values.
    
        def remove(self, key):
            keys = self.key[key]  # Get all the keys that reference the same values as key.
            for key in keys:
                del self.key[key]  # Delete all keys associated with the key.
                del self.value[key]  # Delete all values associated with the key.
    
        def __getitem__(self, key):
            return self.value[key]
    
        def __setitem__(self, key, value):
            keys = self.key[key]  # Get all the keys that reference the same values as key.
            for key in keys:
                self.value[key] = value  # Make all the keys reference the new value.
    
        def __repr__(self):
            output = []
            temp = []
            for key in self.key:
                if key not in temp:
                    temp.extend(self.key[key])
                    output.append("{}: {}".format(self.key[key], self.value[key]))
            return "{" + ", ".join(output) + "}"
    

I tried it out and it does work as expected.

    
    
    a = Foo()
    a.add(["Car", "My_car"], [0, True])
    
    print(a["Car"])  # OUTPUT: [0, True]
    print(a["My_car"])  # OUTPUT: [0, True]
    
    a["Car"][0] = -1
    print(a["Car"])  # OUTPUT: [-1, True]
    print(a["My_car"])  # OUTPUT: [-1, True]
    
    a["Car"][1] = False
    print(a["Car"])  # OUTPUT: [-1, False]
    print(a["My_car"])  # OUTPUT: [-1, False]
    
    a["Car"] = [100, None]
    print(a["Car"])  # OUTPUT: [100, None]
    print(a["My_car"])  # OUTPUT: [100, None]
    
    a["My_car"][0] = -1
    print(a["My_car"])  # OUTPUT: [-1, None]
    print(a["Car"])  # OUTPUT: [-1, None]
    
    a["My_car"][1] = False
    print(a["My_car"])  # OUTPUT: [-1, False]
    print(a["Car"])  # OUTPUT: [-1, False]
    
    a["My_car"] = [100, None]
    print(a["My_car"])  # OUTPUT: [100, None]
    print(a["Car"])  # OUTPUT: [100, None]
    
    print(a)  # OUTPUT: {['Car', 'My_car']: [100, None]}
    a.remove("My_car")
    print(a)  # OUTPUT: {}
    a.add(["Car", "My_car"], [0, True])
    print(a)  # OUTPUT: {['Car', 'My_car']: [0, True]}
    a.remove("Car")
    print(a)  # OUTPUT: {}
    

It works for multiple keys and multiple values as well:

    
    
    a.add(["Car", "My_car"], [0, True])
    a.add(["Boat", "My_boat", "Sea"], [1, False, "testing"])
    a.add(["Soap", "My_soap", "Bath", "Water"], [3])
    
    print(a["Car"])  # OUTPUT: [0, True]
    print(a["My_boat"])  # OUTPUT: [1, False, 'testing']
    print(a["Soap"])  # OUTPUT: [3]
    print(a["Water"])  # OUTPUT: [3]
    

The problem is that it'll might use up some memory when it grows in size.

