views:

145

answers:

4

I have a widget class:

public class Widget
{
    ...
    public string UniqueID = "856D9PWW";
    public int Price = 325;
    public byte[] Data;
    ...
}

I would like a data structure to store my widgets in. Here's the catch - sometimes I need to find a group of widgets based in their price, and sometimes I need to find a specific widget based on it's ID.

I do not want to use two data structures and use each of them when necessary and remove it from the other when I remove it from the first (this includes creating my own data structure that does this 'under the covers'). I would like on data structure, that allows me to use multiple keys, that only needs to remove an item from it using one of the keys, and has the capibility to store multiple items under one of the keys.

+7  A: 

You can create your own data container that maintains the necessary data structures to allow indexing with two keys. If you implement one of the standard container interfaces, you can even use this custom container as any other framework container (of the same kind).

Since you control Add/Remove methods, you can easily make sure the different structures are updates as needed. You can also make sure lookups for both keys are as fast as possible. The fact that the container uses more than one structure to implement the different lookups is an implementation detail.

Brian Rasmussen
Already said I don't want to do that. In my particular situation it is not an implementation detail it is a performance issue.
Steve H.
Sorry, I am not sure I follow you. You don't get performance for free. By implementing your own data container, you can make sure lookups on both keys are as fast as possible. When optimizing code you often have to chose between optimize for space or time. If I understand your question correct, you're looking for fast lookups.
Brian Rasmussen
Agreed - question seems to be "I want something that works exactly like an index, but not an index." +1 for giving the best answer available - creating a simple abstraction over the complex data.
Aaronaught
Agreed. You can get cheap lookups or cheap add/remove. Expecting both is just not the way the world works. Using two private dictionaries is not expensive.
Hans Passant
My question was simple, is there a dictionary with two keys that I don't have to make, and thus far the answer is no. Brian - space is not an issue, I want fast look-up.
Steve H.
There's no dictionary in the .NET framework that supports what you're looking for which is why I suggested you create your own. If you implement the right interfaces, you can even create an implementation, that can be used just like the framework counterpart.
Brian Rasmussen
A: 

To store your data in a relational database you need a single table to store all of your Widget data in (assuming there is no common repeatable data e.g. Widget Type that should be stored in a lookup table - do a search on the web for Database Normalization).

Then once your data table has been created you can retrieve widgets by any combination of fields by using a Database Query.

If you mean a data structure in code just create a list class e.g.

 public class Widgets : List<Widget>{


 } 

and implement different Find methods depending on your search criteria.

Simon Mark Smith
+4  A: 

Would a List of Widgets suffice?

List<Widget> widgetList = new List<Widget>();

widgetList.Add(new Widget(UniqueID, price, data));

//To query by UniqueID
Widget uniqueWidget =  widgetList.Single(x => x.uniqueID.Equals("123"));

//To query by price
List<Widget> widgetsByPrice = widgetList.Where(x => x.price.Equals(100.00));

//To remove
widgetList.Remove(uniqueWidget);
thedugas
Erm, yea, provided I can get Single and Where to work (forgot those existed). And, oh, look, dictionaries have Where as well... So I can put them all in a dictionary keyed with their ID and use WHERE when I need to get the list of prices. You're awesome thedugas!
Steve H.
@Steve: Except this doesn't provide fast lookups, but since you accepted it as an answer, I assume fast lookups wasn't so important after all.
Brian Rasmussen
A: 

There is no magic container that does this. The way database systems handle this is the same way you should: Have a separate index on each access method you need. Yes, it seems ugly, but it's the only way to index on multiple fields. As already mentioned, you can encapsulate this in a class that handles adding and removing elements from each 'index' for you.

Nick Johnson