1
\$\begingroup\$

I have a class called Thing. For simplicity, let's say it initializes with a unique id, and that's all that's unique about it:

class Thing {
  id: string;

  constructor(id: string) {
    this.id = id;
  }
}

Based on its id, a Thing will reference a specific item in the underlying database. It is essentially an abstraction class to help interact with data.

I have a helper class to manage the Things:

class AllTheThings {
  existingThings: Set<Thing> = new Set();
  createThing(id: string){
    const newThing = new Thing(id)
    this.existingThings.add(newThing)
  }
}

Throughout a certain cycle in the code, createThing is called with a variety of ids. That cycle repeats, and createThing may be called again with the same ids from the last cycle. That is fine. But at the start of any cycle, I need to have a list of the unique Things that already have been created in the past.

I need a way to keep a list of unique Things which have been created so far. I initially thought of using a Set, as above. However, due to the repetition, and the fact that I am adding a class instance to a set, the entries repeat. For example:

// cycle1:

AllTheThings.createThing(1)
AllTheThings.createThing(2)


// cycle2:

AllTheThings.createThing(2)
AllTheThings.createThing(3)

My intention at the end of cycle2 is that I would have 3 unique items in the existingThings Set. But I end up with 4. For those not familiar with Set, this is because new Thing(1) !== new Thing(1). While the resulting objects are identical, they are not the same, and they point to different references in memory. I get that.

But the problem remains that I need a list of unique Things that have been created in the past. I am considering doing the following:

class AllTheThings {
  existingThings: Set<string> = new Set();
  createThing(id: string){
    const newThing = new Thing(id)
    this.existingThings.add(id)
  }
}

So in this case, I am keeping a list of unique ids, and I won't get the same type of repetition as before. However, I really need a list of unique Things, not Thing ids. In reality the code is more complex, and a new Thing takes more arguments than just an id. While those arguments are available when calling createThing, they may not be available when accessing existingThings, which means I cannot easily recreate a Thing just from an id where existingThings is used - I need the whole Thing. I can go the route of using a Set of ids, but it would require a lot of refactoring.

Is there a more concise way to maintain a list of unique objects/class instances in a Set?

\$\endgroup\$
2
\$\begingroup\$

One possible workaround could be to use a Map rather than a Set. That way you can store Things by their IDs (which we already know uniquely identify them) and then use those IDs to unambiguously get the Thing back later

Admittedly, this does carry the risk that the IDs get out of sync and the Map ends up associating a Thing with the wrong ID, but it doesn't sound like Things' IDs are meant to change over their lifetimes, in which case it should be safe

\$\endgroup\$
1
  • 1
    \$\begingroup\$ Interesting...I think this is a nice compromise. I can say existingThings: Map<string, Thing> = new Map(), then I can say this.existingThings.set(newThing.id, newThing). Even when that same Thing is created with the same id, it will call .set again, but it won't duplicate, it will just overwrite, which I think will be fine. I will try this, thank you! \$\endgroup\$ Jun 1 at 17:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.