The Only One Around
The Only One Around

Reputation: 181

multiple keys in dict that are the same and are tuples

I have sets of coordinates (in tuples that are the origins) that I am appending into a dictionary, followed by another tuple (the endpoint).

{(0, 0, 0):(10, 10, 10)}

There is a chance that multiple of the same coordinate for the origin will be put into the dict, followed by a different endpoint.

If I try this, they will overwrite, that is why I have tired the method from here where there are mutable objects. The only problem is that if I try and get the x, y and z from it, it turns out the object is not iterable.

Can someone please fix the code from there (will post what I am doing below) or give me a better way to do this? Thanks. (Still new to the mutable objects)

Code:

class coords(object):
    def __init__(self,part): 
        self.part = part
    def __str__(self):
        return self.part

d = {}
d[coords((0, 10, 0))] = (0 ,0 ,0)
d[coords((0, 10, 0))] = (0 ,1 ,0)
d[coords((0, 10, 0))] = (0 ,2 ,0)

for k in d:
    x, y, z = k
    print x,y,z

#Here I get the error: "TypeError: 'coords' object is not iterable" at the line "x, y, z = k"

Upvotes: 0

Views: 475

Answers (4)

bmhkim
bmhkim

Reputation: 774

I'm a little late to the party, but I think this solution should be on the table. A classic (albeit very basic) way to solve having multiple values at any given key in a hash table is to use a list structure to enumerate all of the values with conflicting keys. Best part of this is that you get to use the defaultdict type, with no games/tricks.

d = {}
values = [
    (coords((0, 10, 0)), (0, 0, 0)),
    (coords((0, 10, 0)), (0, 1, 0)),
    (coords((0, 10, 0)), (0, 2, 0)),
]
for start, end in values:
    if start not in d:
        d[start] = []
    d[start].append(end)

for start in d:
    for end in d[start]:
        x, y, z = end
        print x,y,z

It's a lot less surprising to me than @Alfe's solution involving having multiple seemingly matching hash keys, and still lets you use the dict as a proper dict. (otherwise, what's the point?)

Also, you don't need to use a list to store your multiple values, I'm just using a list because it's simple/obvious. You can use a set type (for automatic de-duplication), or another dict if you think you can use a secondary hashing algorithm if you are going to have a lot of conflicts, and so on....

Upvotes: 0

Linuxios
Linuxios

Reputation: 35783

The simplest way to get what you need is to use a list of 2-tuples of endpoints:

endpoint_tuples = [((0, 0, 0), (1, 1, 1)), ((2, 3, 4), (5, 6, 7))]
for start_point, end_point in endpoint_tuples:
  print start_point
  print end_point

If you need to find the endpoint for a certain start point p:

next(endpoints for endpoints in endpoint_tuples if endpoints[0] == p)

Upvotes: 1

Alfe
Alfe

Reputation: 59426

You could use a tuple subclass which has a different behavior concerning equality than the standard tuple.

class htuple(tuple):
  def __hash__(self):
    return id(self)
  def __eq__(self, other):
    return self is other

Now you can create htuples like this: htuple((1,2,3))

And these htuples behave a little like lists (they are equal only on identity) and a mostly like tuples (can be used as dictionary keys, can be iterated, etc.):

{ htuple((1,2,3)): (4,5,6),
  htuple((1,2,3)): (7,8,9) }

This is a hack (and I cannot stress this strongly enough). But maybe in your special situation it is a solution you can live with.

Upvotes: 1

avinash pandey
avinash pandey

Reputation: 1381

You can need to return a string from str not a tuple.Then in the loop just call the dictionary with the key returned from coords str method.

class coords(object):
    def __init__(self,part): 
        self.part = part
    def __str__(self):
        return str(self.part)

d = {}
d[coords((0, 10, 0))] = (0 ,0 ,0)
d[coords((0, 10, 0))] = (0 ,1 ,0)
d[coords((0, 10, 0))] = (0 ,2 ,0)


for k in d:
   x, y, z = d[k]
   print x,y,z

Upvotes: 0

Related Questions