views:

152

answers:

3

Let's say I have a collection of Person objects, each of which looks like this:

class Person 
{
  string Name;
  string UniqueID;
}

Now, the objects must be stored in a container which allows me to order them so that I can given item X easily locate item X+1 and X-1.

However, I also need fast access based on the UniqueID, as the collection will be large and a linear search won't cut it.

My current 'solution' is to use a std::list in conjunction with a std::map. The list holds the Persons (for ordered access) and the map is used to map UniqueID to a reference to the list item. Updating the 'container' typically involves updating both map and list.

It works, but I feel there should be a smarter way of doing it, maybe boost:bimap. Suggestions?

EDIT: There's some confusion about my requirement for "ordering". To explain, the objects are streamed in sequentially from a file, and the 'order' of items in the container should match the file order. The order is unrelated to the IDs.

+8  A: 

boost:bimap is the most obvious choice. bimap is based on boost::multi_index, but bimap has simplified syntax. Personally I will prefer boost::multi_index over boost::bimap because it will allow to easily add more indices to the Person structure in the future.

Kirill V. Lyadvinsky
By the way, question to native speakers: `indices` or `indexes`?
Kirill V. Lyadvinsky
`Indices` is the technically correct plural noun. But everone would understand `indexes`...
Roddy
Thanks. frustratingly I;ve found that my toolchain (C++Builder 2010) doesn't support boost::multi_index or bimap, but hey, at least I know what I *should* be using.
Roddy
+7  A: 

There is no Standard Library container that does what you want - so you will have to use two containers or the Boost solution. If using two containers, I would normally prefer a vector or a deque over a list, in almost all circumstances.

anon
@Neil, Thanks. Using a vector would mean that deleting or inserting an item would potentially invalidate ALL the references in my map. Hence the list.
Roddy
@Roddy: I am unsure of your requirements, but I have an idea that you use your list as a queue. If I am wrong, then please feel free to correct me, but if I am right, then Neil's `deque` solution makes sense.
Matthieu M.
@Matthieu, Sadly not: I still need random insert/delete that won't invalidate locations of all other items.
Roddy
How can you need insertion if the elements are read from a file in a specific order ? It seems to me you would never need anything else than deletion, since records can't magically appear in the file.
Matthieu M.
@Matthieu: Think of it like a text editor: Open a ordered file of 'lines', user then adds/deletes/edits at random, and we finally save out an updated ordered file of lines.
Roddy
+1  A: 

Why not to use two maps , one having Person as Key and another one having UniqueId as Key, but that requires updating both of them.

you can create a callback function which updates both the maps whenever there is any change.

Alien01
@Alien01: "you can create a callback function..." Ah - how do I do that??
Roddy
By reinventing the Bimap :)
Matthieu M.