In my application I create a set of objects, each of which has a name (string) and uuid (string). For this I use a text field, the MBS uuid module and a command button. I would like these objects to be unique. The UUID property helps make the objects unique, but I would like to avoid creating multiple objects with the same name property too.
I initially did this by adding the name and uuid to a listbox and then deduplicating the list. That feels kludgy though, and if possible I’d prefer to use objects all the way. I thought of adding each new object to an array, but from what I’ve read there seems to be no way to de-duplicate an object array.
Can anyone suggest a way to ensure uniqueness, maybe by deduplicating the array of objects? Is there a way to reach into the array object so that I can check the name and uuid properties for its members and maybe use that as a way to identify duplicates?
That’s the idea: If there already is an entry for that string you return that, otherwise you create a new object and add it to the dictionary.
I think it was the LISP language that pioneered that concept: LISP had a Symbols datatype where there was ever only one symbol with a given name. If a a symbol was encountered the LISP interpreter checked whether a hash table of all the known symbols contained a symbol with that name. Only if it didn’t was a new symbol created.
I think that it might be OK. UUIDs are unique by design, so there should never be more than one dictionary entry with that key, provided that I check it.
There’s no theoretical reason you cannot do this, but let’s talk about why you might want to do this. It’s typically good practice for objects to have a single unique identifier by which they are referenced - that way, there’s no ambiguity in your code as to which attribute you store as a foreign key.
On the other hand, if the name attribute is something that the user defines and you want that to be unique, that’s fine and a different story, because you wouldn’t use the name attribute as a key in code, it would only be for display purposes to the user.
This seemed like a nice quick coding challenge so I threw together a project for you to look at. Inside, you’ll find a class called UniqueNameAndIDClass. It uses two Dictionaries to store the UUIDs and the Names. The class’s constructor makes sure that it creates a unique UUID, which is also protected from being altered later. The Name property is also checked against a list which is updated when the Name property is changed. When the class instance is destroyed, both the UUID and the Name are removed from the lists.
This little project uses Shared Methods, Shared Properties, and Computed Properties to implement all this functionality, and the App.Opening event has a quick rundown of how to use the class as well as a few basic tests to make sure it is working as expected.
If the names are not editable after creation, make the UUID a v5 UUID based on the name.
If they are editable, build a fingerprint of the object. Something like Crypto.MD5(Name) is sufficient. While MD5 is not a great choice for many tasks these days, it’ll be super fast and more than sufficient for this task. If name uniqueness is not case sensitive, lowercase the name before generating the hash. With the fingerprint, you can compare that to any other instance of the same object, such as with Operator_Compare, as a dictionary key, or any other way you feel like.
Edit: Nevermind, this is a stupid idea. It’s perfect when you have multiple data points to compare, but for a single string property, there’s absolutely nothing gained from the fingerprint approach.
I was thinking about this as well. If the IDs are never serialized for usage outside the current lifespan of the running app, and don’t ever leave the app, then why not simply use an integer and increment it every time a new instance is created. No chance of namespace collision, easier to understand and remember during debug, the number tells you the order of creation, etc.
They will be stored in some kind of serialised form, which is why I am going for UUIDs. But looking at the responses from you and other colleagues has pointed the way to what I think will work.