-
Notifications
You must be signed in to change notification settings - Fork 3
Examples: RankedDictionary
Kasey O edited this page Oct 12, 2017
·
1 revision
This page contains several examples showing usage of the RankedDictionary
class.
Each example is a complete C# program with output included as comments.
For complete documentation on the Kaos.Collections
namespace including this class, see:
https://kaosborn.github.io/help/KaosCollections/
The first example of the RankedDictionary
class shows some basic operations.
using System;
using System.Collections.Generic;
using Kaos.Collections;
namespace ExampleApp
{
class RdExample01
{
static void Main()
{
// ISO 3166-1 country codes:
var cc = new RankedDictionary<string,string>();
cc.Add ("TO", "Tonga");
cc.Add ("DD", "German Democratic Republic");
cc.Add ("CH", "Switzerland");
cc.Add ("RU", "Burundi");
// The Add method throws an exception if the new key is
// already in the dictionary.
try
{
cc.Add ("DD", "East Germany");
}
catch (ArgumentException)
{
Console.WriteLine ("An element with Key = 'DD' already exists.");
}
// The Item property is another name for the indexer,
// so you can omit its name when accessing elements.
Console.WriteLine ("For key = 'CH', value = {0}.", cc["CH"]);
// The indexer can be used to change the value associated with a key.
cc["RU"] = "Russian Federation";
Console.WriteLine ("For key = 'RU', value = {0}.", cc["RU"]);
// If a key does not exist, setting the indexer for that key
// adds a new key/value pair.
cc["SS"] = "South Sudan";
// The indexer throws an exception if the supplied key is
// not in the dictionary.
try
{
Console.WriteLine ("For key = 'ZZ', value = {0}.", cc["ZZ"]);
}
catch (KeyNotFoundException)
{
Console.WriteLine ("Key = 'ZZ' is not found.");
}
// When a program often has to try keys that are usually not in the
// dictionary, TryGetValue can be a more efficient way to get values.
string value = "";
if (cc.TryGetValue ("ZZ", out value))
Console.WriteLine ("For key = 'ZZ', value = {0}.", value);
else
Console.WriteLine ("Key = 'ZZ' is not found.");
// ContainsKey can be used to test keys before inserting them.
if (! cc.ContainsKey ("GG"))
{
cc.Add ("GG", "Guernsey");
Console.WriteLine ("Value added for key = 'GG': {0}", cc["GG"]);
}
// When you use foreach to enumerate dictionary elements,
// the elements are retrieved as KeyValuePair instances.
Console.WriteLine();
foreach (KeyValuePair<string,string> pair in cc)
Console.WriteLine ("Key = {0}, Value = {1}", pair.Key, pair.Value);
// To get the values alone, use the Values property.
RankedDictionary<string,string>.ValueCollection vals = cc.Values;
// The elements of the ValueCollection are strongly typed
// with the type that was specified for dictionary values.
Console.WriteLine();
foreach(string val in vals)
Console.WriteLine ("Value = {0}", val);
// To get the keys alone, use the Keys property.
RankedDictionary<string,string>.KeyCollection keys = cc.Keys;
// The elements of the KeyCollection are strongly typed
// with the type that was specified for dictionary keys.
Console.WriteLine();
foreach (string key in keys)
Console.WriteLine("Key = {0}", key);
// Use the Remove method to remove a key/value pair.
Console.WriteLine ("\nRemoving 'DD'.");
cc.Remove ("DD");
Console.WriteLine ("\nChecking if 'DD' exists:");
if (! cc.ContainsKey ("DD"))
Console.WriteLine (" Key 'DD' not found.");
}
/* Output:
An element with Key = 'DD' already exists.
For key = 'CH', value = Switzerland.
For key = 'RU', value = Russian Federation.
Key = 'ZZ' is not found.
Key = 'ZZ' is not found.
Value added for key = 'GG': Guernsey
Key = CH, Value = Switzerland
Key = DD, Value = German Democratic Republic
Key = GG, Value = Guernsey
Key = RU, Value = Russian Federation
Key = SS, Value = South Sudan
Key = TO, Value = Tonga
Value = Switzerland
Value = German Democratic Republic
Value = Guernsey
Value = Russian Federation
Value = South Sudan
Value = Tonga
Key = CH
Key = DD
Key = GG
Key = RU
Key = SS
Key = TO
Removing 'DD'.
Checking if 'DD' exists:
Key 'DD' not found.
*/
}
}
The next example shows enumeration of a dictionary's subcollections.
using System;
using Kaos.Collections;
namespace ExampleApp
{
class RdExample02
{
static void Main()
{
var dary = new RankedDictionary<int,int>()
{ [36] = 360, [12] = 120 };
Console.WriteLine ("Keys:");
foreach (var key in dary.Keys)
Console.WriteLine (key);
Console.WriteLine ("\nValues:");
foreach (var val in dary.Values)
Console.WriteLine (val);
}
/* Output:
Keys:
12
36
Values:
120
360
*/
}
}
The next example demonstrates LINQ usage and range queries against a dictionary:
using System;
using System.Linq;
using System.Collections.Generic;
using Kaos.Collections;
namespace ExampleApp
{
class RdExample03
{
static void Main()
{
var towns = new RankedDictionary<string,int>();
// Load sample data.
towns.Add ("Albany", 43600);
towns.Add ("Bandon", 2960);
towns.Add ("Corvallis", 54462);
towns.Add ("Damascus", 10539);
towns.Add ("Elkton", 195);
towns.Add ("Florence", 8466);
towns.Add ("Glide", 1795);
towns.Add ("Jacksonville", 2235);
towns.Add ("Lebanon", 13140);
towns.Add ("Lookingglass", 855);
towns.Add ("Medford", 75180);
towns.Add ("Powers", 689);
towns.Add ("Riddle", 1020);
towns.Add ("Roseburg", 20480);
towns.Add ("Scio", 710);
towns.Add ("Talent", 6066);
towns.Add ("Umatilla", 6906);
towns.Add ("Winston", 5379);
towns.Add ("Yamhill", 820);
// Here's a typical LINQ-To-Objects operation.
double avg = towns.Average (x => x.Value);
Console.WriteLine ("Average population of all towns = {0:f0}", avg);
// Lambda expression
IEnumerable<KeyValuePair<string,int>> r1 = towns.Where (t => t.Key.CompareTo ("E") < 0);
Console.WriteLine ("\nTowns A-D:");
foreach (KeyValuePair<string,int> e in r1)
Console.WriteLine (e.Key);
// LINQ range: O(n)
IEnumerable<KeyValuePair<string,int>> r2 = towns.SkipWhile (t => t.Key.CompareTo ("E") < 0).TakeWhile (t => t.Key.CompareTo ("J") < 0);
Console.WriteLine ("\nTowns E-G:");
foreach (KeyValuePair<string,int> e in r2)
Console.WriteLine (e.Key);
//
// Use the ElementsBetween iterator to query range.
// Unlike LINQ SkipWhile and TakeWhile, this will perform an optimized (partial scan) lookup.
//
// BtreeDictionary range operator: O(log n)
IEnumerable<KeyValuePair<string,int>> r3 = towns.ElementsBetween ("K", "M");
Console.WriteLine ("\nTowns K-L:");
foreach (KeyValuePair<string,int> town in r3)
Console.WriteLine (town.Key);
// Range operator without upper limit: O(log n)
IEnumerable<KeyValuePair<string,int>> r4 = towns.ElementsFrom ("M");
Console.WriteLine ("\nTowns M-R:");
foreach (KeyValuePair<string,int> town in r4)
// This avoids the issue in the last example where a town named "M" would be included.
if (town.Key.CompareTo ("S") >= 0)
break;
else
Console.WriteLine (town.Key);
// Range operator without upper limit: O(log n)
IEnumerable<KeyValuePair<string,int>> r5 = towns.ElementsFrom ("T");
Console.WriteLine ("\nTowns T-Z:");
foreach (KeyValuePair<string,int> town in r5)
Console.WriteLine (town.Key);
}
/* Output:
Average population of all towns = 13447
Towns A-D:
Albany
Bandon
Corvallis
Damascus
Towns E-G:
Elkton
Florence
Glide
Towns K-L:
Lebanon
Lookingglass
Towns M-R:
Medford
Powers
Riddle
Roseburg
Towns T-Z:
Talent
Umatilla
Winston
Yamhill
*/
}
}
The next example shows usage of custom comparers.
using System;
using Kaos.Collections;
namespace ExampleApp
{
class RdExample04
{
static void Main()
{
var dary1 = new RankedDictionary<string,int> (StringComparer.InvariantCultureIgnoreCase);
dary1.Add ("AAA", 0);
dary1.Add ("bbb", 1);
dary1.Add ("CCC", 2);
dary1.Add ("ddd", 3);
Console.WriteLine ("Comparer is case insensitive:");
foreach (System.Collections.Generic.KeyValuePair<string,int> pair in dary1)
Console.WriteLine (pair.Key);
Console.WriteLine();
var dary2 = new RankedDictionary<string,int> (StringComparer.Ordinal);
dary2.Add ("AAA", 0);
dary2.Add ("bbb", 2);
dary2.Add ("CCC", 1);
dary2.Add ("ddd", 3);
Console.WriteLine ("Comparer is case sensitive:");
foreach (System.Collections.Generic.KeyValuePair<string,int> pair in dary2)
Console.WriteLine (pair.Key);
}
/* Output:
Comparer is case insensitive:
AAA
bbb
CCC
ddd
Comparer is case sensitive:
AAA
CCC
bbb
ddd
*/
}
}
The next example shows using a BinaryFormatter to serialize a dictionary to a file stream and read it back.
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using Kaos.Collections;
namespace ExampleApp
{
[Serializable]
public class PersonComparer : Comparer<Person>
{
public override int Compare (Person x, Person y)
{ return x==null? (y==null? 0 : -1) : (y==null? 1 : String.Compare (x.ToString(), y.ToString())); }
}
[Serializable]
public class Person : ISerializable
{
public string First { get; private set; }
public string Last { get; private set; }
public Person (string first, string last)
{ this.First = first; this.Last = last; }
protected Person (SerializationInfo info, StreamingContext context)
{
this.First = (string) info.GetValue ("First", typeof (String));
this.Last = (string) info.GetValue ("Last", typeof (String));
}
public virtual void GetObjectData (SerializationInfo info, StreamingContext context)
{
info.AddValue ("First", First, typeof (String));
info.AddValue ("Last", Last, typeof (String));
}
public override string ToString() => Last + ", " + First;
}
class RdExample05
{
static void Main()
{
IFormatter formatter = new BinaryFormatter();
var set1 = new RankedDictionary<Person,string> (new PersonComparer());
set1.Add (new Person ("Hugh", "Mann"), "B+");
set1.Add (new Person ("Hammond", "Egger"), "C-");
SerializePersons ("Persons.bin", set1, formatter);
Console.WriteLine ("Wrote " + set1.Count + " key/value pairs.");
Console.WriteLine ();
RankedDictionary<Person,string> set2 = DeserializePersons ("Persons.bin", formatter);
Console.WriteLine ("Read back:");
foreach (var kv in set2)
Console.WriteLine (kv);
}
public static void SerializePersons (string fn, RankedDictionary<Person,string> set, IFormatter formatter)
{
using (var fs = new FileStream (fn, FileMode.Create))
{ formatter.Serialize (fs, set); }
}
static RankedDictionary<Person,string> DeserializePersons (string fn, IFormatter formatter)
{
using (var fs = new FileStream (fn, FileMode.Open))
{ return (RankedDictionary<Person,string>) formatter.Deserialize (fs); }
}
/* Output:
Wrote 2 key/value pairs.
Read back:
[Egger, Hammond, C-]
[Mann, Hugh, B+]
*/
}
}