Using Custom Generic Collection faster with objects than List - c#

I'm iterating through a List<> to find a matching element. The problem is that object has only 2 significant values, Name and Link (both strings), but has some other values which I don't want to compare.
I'm thinking about using something like HashSet (which is exactly what I'm searching for -- fast) from .NET 3.5 but target framework has to be 2.0. There is something called Power Collections here: http://powercollections.codeplex.com/, should I use that?
But maybe there is other way? If not, can you suggest me a suitable custom collection?

In .NET 2.0 instead of a HashSet<T> you can use a Dictionary<K, V>.
Dictionary uses the hash code to perform key lookups so it has similar performace to the HashSet. There are at least two approaches:
Create a custom class or struct containing the Name and Link and use that as the key in the dictionary, and put the object as the value.
Store the entire object as the key and provide a custom equality comparer that only looks at the Name and Link member, and set the value to null.
The second method is very similar to how you would use a HashSet if it were available.

How about this:
Custom class/collection wich will held List of objects and two dictionaries, one for the name and one for the link. Both of them will have a int value wich will be the index of object. I think that in that case I will only need to check if there is such int value of name dictionary that equals link dictionary int.
Is this a good approach?

Related

Data type for storing object pair other than Dictionary in C#

What would be the best data type for storing non-unique pairs of objects? I cannot use Dictionary because the key has to be unique. I could create an object with the two data types as properties and store them in a list, but that wouldn't be flexible enough to accommodate the different data type pairs. Something almost like Dictionary but non-unique. A build-in solution from .NET would be even better.
I think a List<Tuple<T1,T2>> would work best here.
List<T>
Tuple<T1,T2>
You could use List<KeyValuePair<T1,T2>>. Dictionary class uses KeyValuePair too.

Which data structure/class I can use to represent one-to-many relation?

I am trying to write a program that would use a data structure/class that will hold multiple data entries for one key - this will be somehow similar to Dictionary but it's not one to one but one to many relation. I am trying to think of a class that I can use but I cannot figure anything out.
For instance how it may look like:
I have a parameter xValue and 3 different values in different files so i would have :
xValue, <1.txt, 1>
xValue, <2.txt, 2>
xValue, <3.txt, 3>
Any ideas ?
EDIT:
I have figured this out - After all I can use
Dictionary< string , Dictionary<..., ... > >
, can't I ?
As there is no multiset in .NET natively, I would go for
Dictionary<Key, HashSet<XValue>>
in your case.
If you are ok with using 3rd-party containers, you can look up the answers from here, e.g., Wintellect PowerCollections.
If you do not need modify this collection after initialization and just need to do search, you can leverage built in Lookup<TKey, TElement> class, but really this would be tricky and useful in rare cases when you already have IEnumerable<> instances and would flatten it to lookup data structure, anyway this is pretty useful to keep in mind that .NET provides such intersting class.
MSDN
Represents a collection of keys each mapped to one or more values. A
Lookup<TKey, TElement> resembles a Dictionary<TKey, TValue>. The
difference is that a Dictionary<TKey, TValue> maps keys to single
values, whereas a Lookup<TKey, TElement> maps keys to collections of
values.
You can not instantiate it explicitly and just can get instance of lookup using LINQ ToLookup() method. There are major restrictions so you can use this class as lookup data structure - doing search.
There is no public constructor to create a new instance of a
Lookup. Additionally, Lookup objects
are immutable, that is, you cannot add or remove elements or keys from
a Lookup object after it has been created.

Dictionary or KeyedCollection?

I have a class (SomeClass) which contains a property Name of string type. And I need to store an array of that class and find its items by their names. For this purpose there are two types of collections: KeyedCollection and Dictionary. My question is: What difference between them and in such case It is better to use KeyedCollection and Dictionary? Thanks for any help in explanation.
None of the previous comments address the most important difference between the two:
KeyedCollection keeps your items in the order in which they are added (the first item added is at index 0 and the last added is at the last index). Dictionary does not (or at least it is never guaranteed to do so).
This extra benefit of KeyedCollection does have a small performance cost. Under the covers, you pay the cost of maintaining both a Dictionary and a List.
Here is good explanation about differences between Dictionary and KeyedCollection: http://geekswithblogs.net/NewThingsILearned/archive/2010/01/07/using-keyedcollectionlttkey-titemgt.aspx
Main points are:
KeyedCollection is abstract, so you can't use it directly.
KeyedCollection is useful for cases, when key is in entity itself, then you can encapsulate key retrieval within collection implementation.
There are generic implementations for KeyedCollection (not in the framework though), which allow you to paste key retrieval delegate in collection constructor, so you don't have to repeat it each time you add item.
Update: as long as original link to article was removed, adding link to web archive: https://web.archive.org/web/20200228045828/http://geekswithblogs.net/NewThingsILearned/archive/2010/01/07/using-keyedcollectionlttkey-titemgt.aspx
A KeyedCollection allows mutable keys and ways to manage change in key. Dictionary does not allow changes to key. Secondly, if you have a collection which needs lookup, the logic to extract key from entity remains in one place - whereas maintaining dictionary will need to put key extraction logic at each place where items are added/removed from dictionary.
By default a KeyedCollection creates a Dictionary under the covers.
If the Key also has meaning as part of the Value and also defines uniqueness then that is the purpose of a KeyedCollection.
If you want to modify the dictionary backing then use this ctor:
protected KeyedCollection(
IEqualityComparer<TKey> comparer,
int dictionaryCreationThreshold)
A KeyedCollection should be used when the key is on the item itself.
By default, KeyedCollection is a Collection<TItem> wrapper around a dictionary. When you use small collections and/or you prefer retrieving items directly, the KeyedCollection provides a constructor that takes a dictionaryCreationThreshold parameter, that indicates at what collection count to switch to Dictionary.
Another aspect in KeyedCollection is that you can choose to switch the key property (as long as their types match). This can be good for double keyed items etc.
Performancewise, I don't think wrapping a dictionary has much overhead except if you generate a bunch of KeyedCollection instances, or if you use really large collections (there are some internal null checks to determine if there is a dictionary).
One thing I'd hope to see in KeyedCollection is unabstracting it, but you can make a generic concrete type just as easy.
You can't use KeyedCollection because it's abstract: http://msdn.microsoft.com/en-us/library/ms132438.aspx. This means you can't create an object of it.

custom sorting of Hashtable in C# (not by keys)

I need to sort the data in a Hashtable by a property of the object added to the collection. how to do that? my project uses .NET 2.0, so I can't use any features that do not work by default in .NET 2.0 runtime (I may be able to use some of the C# 3.0 features that will work on .NET 2.0 without adding references to any new dlls). all the objects added to hashtable are of the same type. If I use SortedList and pass Hashtable to it (through constructor), then it sorts only by keys, is there a way to pass custom sorting logic to it?
if you are bound to .NET 2.0 you can use IComparer.
http://codebetter.com/davidhayden/2005/02/27/implementing-icomparable-for-sorting-custom-objects/
a Hashtable is definetly the wrong datastructure if you want to sort something.
#Snoopy said IComparer, that is indeed what you need. Take a look at SortedDictionary.
Take a look at the drawbacks of a hash table. Then look at the advantages and determine if you are using the right data structure. If you very rarely sort, then you may be using the right data structure. In this case, sorting will require you enumerate the values and put them into a list. If sort if frequent, consider moving to a different data structure, like a search tree. If you rarely do lookups/searches, I would consider using an ordinary list.
One option, if you want to stick to creating a sorted list from the contents of a Hashtable, is to write a subclass of IComparer, overload the Compare method as needed, and create a Sorted list using:
SortedList s = new SortedList( new MyIComparer() );
Then add the elements of your Hashtable to the list accordingly.

How to get a unique object reference as a string for items in a list

I'm working on a .NET phone application where I have a list of items in memory that are displayed to the user. When the user clicks on an item in the user interface, they'll be brought to the "details" view for that item in a second view. I'm currently using an identity property in my class to reference unique items in the list, but I'm wondering if there is a better way.
I'm using System.Windows.Navigationto set up UriMappings like so:
<nav:UriMapping Uri="/Items/{itemId}"
MappedUri="/Views/Items.xaml?itemId={itemID}" />
I then use the NavigationService to navigate like so:
NavigationService.Navigate(new Uri("/Items/" + item.id.ToString(),
UriKind.Relative));
All of this works great, but I don't know that I like needing to include an identity column for my Item class just so that can have a unique string identifer to pass in to the MappedUri query string. My user interface control that shows the list gives me the underlying Item object in the SelectionChanged event, so I'm wondering if there's a way to "match" that Item object with a unique string value to its corresponding reference in the list. If I could provide a simple object reference to the navigation service, this would be easy, but I'm not sure how to do it with a string value. Is this what GetHashCode() is for, and if so, how do I use it correctly?
No, GetHashCode is not intended to uniquely identify objects.
The default implementation of the GetHashCode method does not guarantee unique return values for different objects. Furthermore, the .NET Framework does not guarantee the default implementation of the GetHashCode method, and the value it returns will be the same between different versions of the .NET Framework. Consequently, the default implementation of this method must not be used as a unique object identifier for hashing purposes.
It is designed for storing objects in buckets (for example in a dictionary) so that they can be quickly retrieved. The hash codes for two equal objects must be equal, but the hash codes for two different objects do not have to be different.
I think adding an Id field is a fine solution. If you don't like adding a new field just to give an object an identity you can try to find some combination of the existing fields that is guarateed to uniquely identify your object and concetenate their string representations with a suitable separator. Be careful that the separator cannot occur in any of the fields.
There's a GUID which you can use that maps to each string in the list, by calling a NewGuid method of the Guid class, one can generate a Guid and use that as a string type via ToStringmethod and use it for hashing strings.
You definitely want to provide the item's ID. Bear in mind that your application may be tombstoned, so the object may not even be in memory any more when you try to navigate to that page. You need to be able to restore the application to the page with no information other than the URL and whatever's been serialized to temporary or permanent storage (typically in OnNavigateFrom).
Using GetHashCode() for this not only doesn't guarantee uniqueness, but it's highly unlikely to work in terms of the newly restored application, too. Life gets a lot harder when you're trying to display the details of something where you haven't really got an ID... but it doesn't sound like you're really in that position.
As it looks like you've got an ID, use it as an ID. Why would you want to use anything else? If you don't have an ID but can easily add one, do so. You want a way of uniquely identifying an object... that's exactly what an ID is for.

Categories