SortedList or Dictionary of KEYS ONLY

P

pamela fluente

I noticed that I am using quite often SortedLists where I use KEYS
only.

when I add new elements I use something like : MyKeyObj ,
Nothing/Null/false

Is there a collection type which is similar to the SortedList by does
NOT
have the Values ?

And, a similar question, I have for the Dictionary.


-P
 
A

Armin Zingler

pamela fluente said:
I noticed that I am using quite often SortedLists where I use KEYS
only.

when I add new elements I use something like : MyKeyObj ,
Nothing/Null/false

Is there a collection type which is similar to the SortedList by
does NOT
have the Values ?

And, a similar question, I have for the Dictionary.

Did you know that there are .Net Framework groups for language independent
questions? You can find them here: m.p.dotnet.framework[.*]


Armin
 
S

Samuel R. Neff

We use a custom collection called KeySet<T> for a dictionary of keys
only since this scenario comes up a lot. It's made programming these
things a lot easier to read and maintain.

Watch the line wrapping...

HTH,

Sam

------------------------------------------------------------
We're hiring! B-Line Medical is seeking .NET
Developers for exciting positions in medical product
development in MD/DC. Work with a variety of technologies
in a relaxed team environment. See ads on Dice.com.


using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;

namespace Common
{
/// <summary>
/// Provides a collection of unordered unique keys.
/// </summary>
/// <typeparam name="T">The type of keys to collection</typeparam>
/// <remarks>
/// KeySet is similar to a Dictionary but does not contain a value
and is useful when one only cares about existence of
/// keys and not values associated with them.
/// </remarks>
[DebuggerStepThrough]
public class KeySet<T> : IDictionary<T, bool>, ICollection<T>,
IEnumerable<T>, ICollection
{
#region Data

private Dictionary<T, bool> _dictionary;

#endregion

#region Constructors

public KeySet() : this(0)
{
}

public KeySet(IEqualityComparer<T> comparer) : this(0, comparer)
{
}

public KeySet(int capactity)
: this(capactity, null)
{
}

public KeySet(int capactity, IEqualityComparer<T> comparer)
{
_dictionary = new Dictionary<T, bool>(capactity, comparer);
}

public KeySet(ICollection<T> collection) : this(collection, null)
{
}

public KeySet(ICollection<T> collection, IEqualityComparer<T>
comparer)
{
if (collection == null)
{
throw new ArgumentNullException("collection");
}
_dictionary = new Dictionary<T, bool>(collection.Count,
comparer);
foreach (T key in collection)
{
_dictionary[key] = true;
}
}

#endregion

#region Public Properties

public int Count
{
get
{
return _dictionary.Count;
}
}

public ICollection<T> Keys
{
get
{
return _dictionary.Keys;
}
}

public bool IsReadOnly
{
get
{
return false;
}
}

/// <summary>
/// Returns true if the key exists in the collection, false
otherwise.
/// </summary>
/// <param name="key">Key to check for.</param>
/// <returns>True if key exists in collection.</returns>
/// <remarks>
/// Setting a value to false will remove the key from the
collection if it exists.
///
/// Unlike IDictionary&lt;&gt> the indexer will not throw an
exception on an non-existent key, it will simply return false.
/// </remarks>
public bool this[T key]
{
get
{
return _dictionary.ContainsKey(key);
}
set
{
if (value)
{
_dictionary[key] = true;
}
else
{
_dictionary.Remove(key);
}
}
}

#endregion

#region Public Methods

public void Add(T key)
{
_dictionary.Add(key, true);
}

public void Add(ICollection<T> collection)
{
if (collection == null)
{
throw new ArgumentNullException("collection");
}
foreach(T key in collection)
{
_dictionary.Add(key, true);
}
}

///<summary>
///Removes all items from the <see
cref="T:System.Collections.Generic.ICollection`1"></see>.
///</summary>
///
///<exception cref="T:System.NotSupportedException">The <see
cref="T:System.Collections.Generic.ICollection`1"></see> is read-only.
</exception>
public void Clear()
{
_dictionary.Clear();
}

public bool Contains(T key)
{
return _dictionary.ContainsKey(key);
}

public void CopyTo(T[] array, int arrayIndex)
{
_dictionary.Keys.CopyTo(array, arrayIndex);
}

public IEnumerator<T> GetEnumerator()
{
return _dictionary.Keys.GetEnumerator();
}

public bool Remove(T key)
{
return _dictionary.Remove(key);
}

public bool TryGetValue(T key, out bool value)
{
return _dictionary.TryGetValue(key, out value);
}

#endregion

#region IDictionary<T,bool> Members

///<summary>
///Adds an element with the provided key and value to the <see
cref="T:System.Collections.Generic.IDictionary`2"></see>.
///</summary>
///
///<param name="value">The bool to use as the value of the element
to add.</param>
///<param name="key">The bool to use as the key of the element to
add.</param>
///<exception cref="T:System.NotSupportedException">The <see
cref="T:System.Collections.Generic.IDictionary`2"></see> is
read-only.</exception>
///<exception cref="T:System.ArgumentException">An element with
the same key already exists in the <see
cref="T:System.Collections.Generic.IDictionary`2"></see>.</exception>
///<exception cref="T:System.ArgumentNullException">key is
null.</exception>
void IDictionary<T, bool>.Add(T key, bool value)
{
if (!value)
{
throw TrueOnlyException;
}
_dictionary.Add(key, true);
}

///<summary>
///Determines whether the <see
cref="T:System.Collections.Generic.IDictionary`2"></see> contains an
element with the specified key.
///</summary>
///
///<returns>
///true if the <see
cref="T:System.Collections.Generic.IDictionary`2"></see> contains an
element with the key; otherwise, false.
///</returns>
///
///<param name="key">The key to locate in the <see
cref="T:System.Collections.Generic.IDictionary`2"></see>.</param>
///<exception cref="T:System.ArgumentNullException">key is
null.</exception>
bool IDictionary<T, bool>.ContainsKey(T key)
{
return _dictionary.ContainsKey(key);
}

///<summary>
///Gets an <see
cref="T:System.Collections.Generic.ICollection`1"></see> containing
the values in the <see
cref="T:System.Collections.Generic.IDictionary`2"></see>.
///</summary>
///
///<returns>
///An <see
cref="T:System.Collections.Generic.ICollection`1"></see> containing
the values in the bool that implements <see
cref="T:System.Collections.Generic.IDictionary`2"></see>.
///</returns>
///
ICollection<bool> IDictionary<T, bool>.Values
{
get
{
return _dictionary.Values;
}
}

#endregion

#region ICollection<KeyValuePair<T,bool>> Members

///<summary>
///Removes the first occurrence of a specific bool from the <see
cref="T:System.Collections.Generic.ICollection`1"></see>.
///</summary>
///
///<returns>
///true if item was successfully removed from the <see
cref="T:System.Collections.Generic.ICollection`1"></see>; otherwise,
false. This method also returns false if item is not found in the
original <see
cref="T:System.Collections.Generic.ICollection`1"></see>.
///</returns>
///
///<param name="item">The bool to remove from the <see
cref="T:System.Collections.Generic.ICollection`1"></see>.</param>
///<exception cref="T:System.NotSupportedException">The <see
cref="T:System.Collections.Generic.ICollection`1"></see> is
read-only.</exception>
bool ICollection<KeyValuePair<T, bool>>.Remove(KeyValuePair<T,
bool> item)
{
return _dictionary.Remove(item.Key);
}

///<summary>
///Copies the elements of the <see
cref="T:System.Collections.Generic.ICollection`1"></see> to an <see
cref="T:System.Array"></see>, starting at a particular <see
cref="T:System.Array"></see> index.
///</summary>
///
///<param name="array">The one-dimensional <see
cref="T:System.Array"></see> that is the destination of the elements
copied from <see
cref="T:System.Collections.Generic.ICollection`1"></see>. The <see
cref="T:System.Array"></see> must have zero-based indexing.</param>
///<param name="arrayIndex">The zero-based index in array at which
copying begins.</param>
///<exception
cref="T:System.ArgumentOutOfRangeException">arrayIndex is less than
0.</exception>
///<exception cref="T:System.ArgumentNullException">array is
null.</exception>
///<exception cref="T:System.ArgumentException">array is
multidimensional.-or-arrayIndex is equal to or greater than the length
of array.-or-The number of elements in the source <see
cref="T:System.Collections.Generic.ICollection`1"></see> is greater
than the available space from arrayIndex to the end of the destination
array.-or-Type T cannot be cast automatically to the type of the
destination array.</exception>
void ICollection<KeyValuePair<T, bool>>.CopyTo(KeyValuePair<T,
bool>[] array, int arrayIndex)
{
((ICollection<KeyValuePair<T, bool>>) _dictionary).CopyTo(array,
arrayIndex);
}

///<summary>
///Determines whether the <see
cref="T:System.Collections.Generic.ICollection`1"></see> contains a
specific value.
///</summary>
///
///<returns>
///true if item is found in the <see
cref="T:System.Collections.Generic.ICollection`1"></see>; otherwise,
false.
///</returns>
///
///<param name="item">The bool to locate in the <see
cref="T:System.Collections.Generic.ICollection`1"></see>.</param>
bool ICollection<KeyValuePair<T, bool>>.Contains(KeyValuePair<T,
bool> item)
{
return _dictionary.ContainsKey(item.Key);
}

///<summary>
///Adds an item to the <see
cref="T:System.Collections.Generic.ICollection`1"></see>.
///</summary>
///
///<param name="item">The bool to add to the <see
cref="T:System.Collections.Generic.ICollection`1"></see>.</param>
///<exception cref="T:System.NotSupportedException">The <see
cref="T:System.Collections.Generic.ICollection`1"></see> is
read-only.</exception>
void ICollection<KeyValuePair<T, bool>>.Add(KeyValuePair<T, bool>
item)
{
if (item.Value)
{
throw TrueOnlyException;
}
_dictionary.Add(item.Key, true);
}

#endregion

#region ICollection Members

///<summary>
///Copies the elements of the <see
cref="T:System.Collections.ICollection"></see> to an <see
cref="T:System.Array"></see>, starting at a particular <see
cref="T:System.Array"></see> index.
///</summary>
///
///<param name="array">The one-dimensional <see
cref="T:System.Array"></see> that is the destination of the elements
copied from <see cref="T:System.Collections.ICollection"></see>. The
<see cref="T:System.Array"></see> must have zero-based indexing.
</param>
///<param name="index">The zero-based index in array at which
copying begins. </param>
///<exception cref="T:System.ArgumentNullException">array is null.
</exception>
///<exception cref="T:System.ArgumentOutOfRangeException">index is
less than zero. </exception>
///<exception cref="T:System.ArgumentException">array is
multidimensional.-or- index is equal to or greater than the length of
array.-or- The number of elements in the source <see
cref="T:System.Collections.ICollection"></see> is greater than the
available space from index to the end of the destination array.
</exception>
///<exception cref="T:System.InvalidCastException">The type of the
source <see cref="T:System.Collections.ICollection"></see> cannot be
cast automatically to the type of the destination array.
</exception><filterpriority>2</filterpriority>
void ICollection.CopyTo(Array array, int index)
{
((IDictionary) _dictionary).Keys.CopyTo(array, index);
}

///<summary>
///Gets an object that can be used to synchronize access to the
<see cref="T:System.Collections.ICollection"></see>.
///</summary>
///
///<returns>
///An object that can be used to synchronize access to the <see
cref="T:System.Collections.ICollection"></see>.
///</returns>
///<filterpriority>2</filterpriority>
object ICollection.SyncRoot
{
get
{
return ((ICollection) _dictionary).SyncRoot;
}
}

///<summary>
///Gets a value indicating whether access to the <see
cref="T:System.Collections.ICollection"></see> is synchronized (thread
safe).
///</summary>
///
///<returns>
///true if access to the <see
cref="T:System.Collections.ICollection"></see> is synchronized (thread
safe); otherwise, false.
///</returns>
///<filterpriority>2</filterpriority>
bool ICollection.IsSynchronized
{
get
{
return ((ICollection)_dictionary).IsSynchronized;
}
}

#endregion

#region IEnumerable<KeyValuePair<T,bool>> Members

///<summary>
///Returns an enumerator that iterates through the collection.
///</summary>
///
///<returns>
///A <see cref="T:System.Collections.Generic.IEnumerator`1"></see>
that can be used to iterate through the collection.
///</returns>
///<filterpriority>1</filterpriority>
IEnumerator<KeyValuePair<T, bool>> IEnumerable<KeyValuePair<T,
bool>>.GetEnumerator()
{
return ((IEnumerable<KeyValuePair<T, bool>>)
_dictionary).GetEnumerator();
}

#endregion

#region IEnumerable Members

///<summary>
///Returns an enumerator that iterates through a collection.
///</summary>
///
///<returns>
///An <see cref="T:System.Collections.IEnumerator"></see> bool
that can be used to iterate through the collection.
///</returns>
///<filterpriority>2</filterpriority>
IEnumerator IEnumerable.GetEnumerator()
{
return _dictionary.Keys.GetEnumerator();
}

#endregion

#region Private Helpers

private static ArgumentException TrueOnlyException
{
get
{
return new ArgumentException("KeySet only supports 'true'
values.");
}
}

#endregion

}
}
 
P

pamela fluente

We use a custom collection called KeySet<T> for a dictionary of keys
only since this scenario comes up a lot. It's made programming these
things a lot easier to read and maintain.

Watch the line wrapping...

HTH,

Sam

Thanks Sam,

It's very generous of you to provide your code.

I was also thinking to do the same (actually more simple :). By
inheriting from
a SortedList of Key, Boolean or a Dictionary of Key, Boolean and
"shielding"
the Values.

But I guess that would not be much different from using the standard
classes and adding Null Values.

It's strange Microsoft dose not seem to provide them (does it?).
Since one has custom comparers in .NET
its quite natural that the Key can hold all the necessary
information. No?

-P
 
P

pamela fluente

Did you know that there are .Net Framework groups for language independent
questions? You can find them here: m.p.dotnet.framework[.*]

you do not want me here !? :))


Cheers,

-P



PS
Thanks, actually I did not know that!
 
A

Armin Zingler

pamela fluente said:
Did you know that there are .Net Framework groups for language
independent questions? You can find them here:
m.p.dotnet.framework[.*]

you do not want me here !? :))

I didn't say this. You're always welcome! Just makes sense to use the groups
for which they are made for. :)


Armin
 
N

Niels Ull

You might want to look into one of the free collection libraries, e.g. "C5"
or "Power Collections" - these have lots of diffrent Set implementations.
 
P

pamela fluente

You might want to look into one of the free collection libraries, e.g. "C5"
or "Power Collections" - these have lots of diffrent Set implementations.

I have just looked at Power Collections. I did not know they existed.

Thanks,

-P
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top