3

Essentially this is what I'm trying to do:

I have a set that I add objects to. These objects have their own equality method, and a set should never have an element equal to another element in the set. However, when attempting to insert an element, if it is equal to another element, I'd like to record a merged version of the two elements. That is, the objects have an "aux" field that is not considered in its equality method. When I'm done adding things, I would like an element's "aux" field to contain a combination of all of the "aux" fields of equal elements I've tried to add.

My thinking was, okay, before adding an element to the set, check to see if it's already in the set. If so, pull it out of the set, combine the two elements, then put it back in. However, the remove method in Python sets doesn't return anything and the pop method returns an arbitrary element.

Can I do what I'm trying to do with sets in Python, or am I barking up the wrong tree (what is the right tree?)

Mala
  • 14,178
  • 25
  • 88
  • 119

1 Answers1

3

Sounds like you want a defaultdict

from collections import defaultdict
D = defaultdict(list)
D[somekey].append(auxfield)

Edit: To use your merge function, you can combine the code people have given in the comments

D = {}
for something in yourthings:
    if something.key in D:
        D[something.key] = something.auxfield
    else:
        D[something.key] = merge(D[something.key], something.auxfield)
John La Rooy
  • 295,403
  • 53
  • 369
  • 502
  • What would be the value (default or not)? Leaving aside that `set` may not offer the necessary functionality, a mapping seems conceptually wrong here. –  May 28 '13 at 23:09
  • +1 this works because it gives uniqueness of keys like a set but with arbitrarily long attributes like Mala requested. I see no conceptual defect `if key in D then: if not aux in D[key]: D[key].append[aux]` – msw May 28 '13 at 23:16
  • thanks! A few questions: (1) would this have a similar memory-footprint to using sets? I'm working under low memory assumptions (2) what would I use as 'somekey'? a hash? (3) would this still work if my merge is a function? appending the values was simplifying it somewhat, but i have a merge(object, object) function – Mala May 28 '13 at 23:20
  • Try showing some code, your questions are a little abstract for concrete answers. – msw May 28 '13 at 23:22
  • @Mala, you can use a hash for the key if that's what you are using for your equality operator. In that case, and if you are using your own merge function, you don't even need a defaultdict. You could use `D = {}`, and `D[obj.Hash()] = merge(D[obj.Hash()], obj)` or something similar. – Markku K. May 28 '13 at 23:31
  • @Markku ah makes a lot of sense, thanks! okay so somekey is something that will be the same for all elements who are equal. I understand now :) I'll play with it and see what memory looks like, but for now this looks like the answer I was looking for. Thanks! – Mala May 28 '13 at 23:33
  • @msw unfortunately I can't; but this looks like it'll work just fine :) – Mala May 28 '13 at 23:34
  • awesome, this turned out to be perfect. Thanks everyone! – Mala May 29 '13 at 17:51