Sorting in Dictionary C# - c#

I Have one Dictionary
Dictionary<string, string> rList = new Dictionary<string, string>();
rList .Add("/a/b/c", "35");
rList .Add("/a/c/f/v", "25");
rList .Add("/a/r/d/c/r/v", "29");
rList .Add("/a", "21");
rList .Add("/a/f, "84");
I just want to sort this Dictionary based on the number of number of '/' present in the key. my expected out put is ,
("/a/r/d/c/r/v", "29")
("/a/c/f/v", "25")
("/a/b/c", "35")
("/a/f, "84")
("/a", "21")

The Dictionary<TKey, TValue> type is an unordered collection in .Net. If you want ordering then you need to use SortedDictionary<TKey, TValue> instead and provide a custom IComparer<string> which counts the / values in the string.
sealed class SlashComparer : IComparer<string> {
static int CountSlashes(string str) {
if (String.IsNullOrEmpty(str)) {
return 0;
}
int count = 0;
for (int i = 0; i < str.Length; i++) {
if (str[i] == '/') {
count++;
}
}
return count;
}
public int Compare(string left, string right) {
int leftCount = CountSlashes(left);
int rightCount = CountSlashes(right);
return rightCount - leftCount;
}
}
To use with a SortedDictionary the only thing you need to change is the declaration
var comparer = new SlashComparer();
var rList = new SortedDictionary<string, string>(comparer);
The rest of the code can remain the same

As JaredPar answered already Dictionary<TKey, TValue> content has no order specified. However, you can get List<KeyValuePair<TKey, TValue>> with desired order:
List<KeyValuePair<string, string>> results = rList.OrderByDescending(x => x.Key.Count(c => c == '/')).ToList();

Try this:
var result = rList.OrderBy(input => input.Key.Select(c => c == '/').Count()).Reverse().ToList();

from linqpad:
void Main()
{
Dictionary<string, string> rList = new Dictionary<string, string>();
rList .Add("/a/b/c", "35");
rList .Add("/a/c/f/v", "25");
rList .Add("/a/r/d/c/r/v", "29");
rList .Add("/a", "21");
rList .Add("/a/f", "84");
var x = from a in rList
let i = a.Key.ToCharArray().Count (k => k.Equals('/') )
orderby i descending
select a;
x.Dump();
}

Related

How to lookup the value of a dictionary inside a dictionary in C#?

I have this transitionMap: Dictionary<Dictionary<int, char>, int> transitionMap;
And I also have this dictionary: Dictionary<int, char> dictionary = new Dictionary<int, char> {{0, 'a'}};.
How do I get the value inside transitionMap that corresponds to dictionary1.
This is what I've tried:
Dictionary<int, char> dictionary = new Dictionary<int, char> {{stateNum, symbol}};
if (this.transitionMap.ContainsKey(dictionary))
{
int nextState = this.transitionMap[dictionary];
Console.WriteLine("nextstate {0}", nextState);
}
If you want to compare two dictionaries for equality then having a "super dictionary" will not help you in any way. You will have to manually compare all elements in two dictionaries.
First, compare the number of elements. Then run a loop through one dictionary, and with the key find the value in second dictionary, and if exists compare two values.
Solution with Linq :
class Program
{
static void Main(string[] args)
{
var transitionMap = new Dictionary<Dictionary<int, char>, int>();
var dictionary = new Dictionary<int, char> { { stateNum, symbol } };
...
var found = transitionMap.Keys.FirstOrDefault(d => Equal(d, dictionary));
if(found == null)
{
int nextState = transitionMap[found];
Console.WriteLine("nextstate {0}", nextState);
}
}
static bool Equal(Dictionary<int, char> a, Dictionary<int, char> b)
{
return a.Count == b.Count && a.All(akv => b.TryGetValue(akv.Key, out char bval) && akv.Value == bval);
}
}

Loop through multiple dictionaries

I have 6 dictionaries. I want to compare another dictionaries against each one of them and see what dictionaries contains what strings. Is it possible to do with a foreach loop?
static Dictionary<string, int> d = new Dictionary<string, int>();
static Dictionary<string, double> dNL = new Dictionary<string, double>();
static Dictionary<string, double> dDE = new Dictionary<string, double>();
static Dictionary<string, double> dFR = new Dictionary<string, double>();
static Dictionary<string, double> dSP = new Dictionary<string, double>();
static Dictionary<string, double> dEN = new Dictionary<string, double>();
static Dictionary<string, double> dIT = new Dictionary<string, double>();
foreach (var f in d)
{
if (dNL.ContainsKey(f.Key))
{
//add to a numeric?
}
if (dDE.ContainsKey(f.Key))
{
//add to a numeric?
}
}
something like this?
what I currently have (and not working like intended):
// need to find a better solution
foreach (var f in d)
{
if (dNL.ContainsKey(f.Key))
{
dNLtotaal++;
}
}
foreach (var f in d)
{
if (dDE.ContainsKey(f.Key))
{
dDEtotaal++;
}
}
foreach (var f in d)
{
if (dFR.ContainsKey(f.Key))
{
dFRtotaal++;
}
}
foreach (var f in d)
{
if (dSP.ContainsKey(f.Key))
{
dSPtotaal++;
}
}
foreach (var f in d)
{
if (dEN.ContainsKey(f.Key))
{
dENtotaal++;
}
}
foreach (var f in d)
{
if (dIT.ContainsKey(f.Key))
{
dITtotaal++;
}
}
// NEED A MUCH BETTER SOLUTION
List<int> totaleD = new List<int>();
totaleD.Add(dNLtotaal);
totaleD.Add(dDEtotaal);
totaleD.Add(dFRtotaal);
totaleD.Add(dSPtotaal);
totaleD.Add(dENtotaal);
totaleD.Add(dITtotaal);
int max = !totaleD.Any() ? -1 : totaleD.Select((value, index) => new { Value = value, Index = index }).Aggregate((a, b) => (a.Value > b.Value) ? a : b).Index;
var maxIndex = totaleD.IndexOf(totaleD.Max());
Console.WriteLine(maxIndex);
You can do something like this:
var items = d.Keys;
var dictionaries = new[] { dNL, dDE, dFR, dSP, dEN, dIT };
var result = dictionaries.Select((d, index) =>
new {
Index = index,
Matches = items.Count(i => d.ContainsKey(i))
})
.OrderByDescending(i => i.Matches)
.Select(i => i.Index)
.FirstOrDefault();
Which gives you the index of the dictionary with the most matches
You could use lambda expressions to get the desired results. In following example, I tried to use two dictionaries:
int dNLtotaal = 0;
Dictionary<string, double> dNL = new Dictionary<string, double>();
Dictionary<string, double> dDE = new Dictionary<string, double>();
dNL.Keys.Where(k => dDE.ContainsKey(k)).ToList().ForEach(k => dNLtotaal++);
Hope it helps
Why not to have 1 Dictionary instead of 6? And keep there a pair [string, List[SomeObject]] where SomeObject is a class like
class SomeObject
{
public Enum Type;//dNL, dDE etc
public double Value;
}

Mapping from 2D array in C#

I want to use a 2-D array in C#, e.g:
string[,] a = new string[,]
{
{"aunt", "AUNT_ID"},
{"Sam", "AUNT_NAME"},
{"clozapine", "OPTION"},
};
My requirement is that when I pass "aunt" to this array I want to get corresponding AUNT_ID from the 2-D array.
As others have said, a Dictionary<string, string> would be better - and you can use a collection initializer to create it simply:
Dictionary<string, string> dictionary = new Dictionary<string, string>
{
{"ant", "AUNT_ID"},
{"Sam", "AUNT_NAME"},
{"clozapine", "OPTION"},
};
If you're confident that your key is in the dictionary, and you're happy for an exception to be thrown otherwise:
string value = dictionary[key];
or if it might not be:
string value;
if (dictionary.TryGetValue(key, out value))
{
// Use value here
}
else
{
// Key wasn't in dictionary
}
If you really need to use an array, if you can change it to a multidimensional array (string[][]), you can use:
// Will throw if there are no matches
var value = array.First(x => x[0] == key)[1];
Or again to be more circumspect:
var pair = array.FirstOrDefault(x => x[0] == key);
if (pair != null)
{
string value = pair[1];
// Use value here
}
else
{
// Key wasn't in dictionary
}
LINQ unfortunately doesn't work quite as well on rectangular arrays. It probably wouldn't be too hard to write a method to allow it to be treated "somewhat" like an array of arrays, admittedly...
Use Dictionary<string, string> for that:
Dictionary<string, string> arr = new Dictionary<string, string>();
arr.Add("ant", "AUNT_ID");
arr.Add("Sam", "AUNT_NAME");
arr.Add("clozapine", "OPTION");
string k = arr["ant"]; // "AUNT_ID"
The best option for you is to use Dictionary, but if you still wants to use 2D array, you may try the following
string[,] a = new string[,]
{
{"ant", "AUNT_ID"},
{"Sam", "AUNT_NAME"},
{"clozapine", "OPTION"},
};
string search = "ant";
string result = String.Empty;
for (int i = 0; i < a.GetLength(0); i++) //loop until the row limit
{
if (a[i, 0] == search)
{
result = a[i, 1];
break; //break the loop on find
}
}
Console.WriteLine(result); // this will display AUNT_ID
It looks rather like you want a dictionary:
Dictionary<string, string> a = new Dictionary<string, string>();
a.Add("ant", "AUNT_ID");
a.Add("Sam", "AUNT_NAME");
a.Add("clozapine", "OPTION");
string s = a["ant"]; // gets "AUNT_ID"
To check if a key exists in the dictionary:
if (a.ContainsKey("ant")) {
...
}
Or:
string s;
if (a.TryGetValue("ant", out s)) {
...
}
for (i=0; i<3; i++){
if (!String.Compare(a[i][0], string)){
stored_string= a[i][1];
}
}

how to use this definition in c# with dictionaries

GROUP["10"]["MATH"] = 30;
GROUP["11"]["MATH"] = 40;
GROUP["9"]["CHEM"] = 50;
...
Can u tell me how to use it with dictionaries. How to define a dictionary for this example?
Dictionary<string,Dictionary<string,int>>
The first [] returns a dictionary, and the second [] operates on that dictionary and returns an int
Dictionary<string, Dictionary<string, int>>
Use:
Dictionary<string, Dictionary<string, int>> dic = new Dictionary<string, Dictionary<string, int>>();
Dictionary<string, int> inner = new Dictionary<string, int>();
inner.Add("MATH", 30);
dic.Add("10", inner);
...
Access
dic["10"]["MATH"]
use this one ......
Dictionary<string,Dictionary<string,int>>
pls go through this link for more info ....On dictionaries,if you are new to dictionaries..
http://msdn.microsoft.com/en-us/library/xfhwa508.aspx
You could create a Dictionary<Tuple<string, string>, int> but you may better defining a class/ custom collection to better represent this, it depends on what your use case is.
An example of Dictionary<Tuple<string, string>, int>
var dict = new Dictionary<Tuple<string, string>, int>
{
{ new Tuple<string,string>("10", "MATH"), 30 },
{ new Tuple<string,string>("11", "MATH"), 40 },
{ new Tuple<string,string>("9", "CHEM"), 50 }
};
Option 1: Use a Dictionary<string, Dictionary<string, int>>.
Dictionary<string, int> group10 = new Dictionary<string, int>();
group10.Add("MATH", 30);
Dictionary<string, int> group11 = new Dictionary<string, int>();
group10.Add("MATH", 40);
Dictionary<string, int> group9 = new Dictionary<string, int>();
group10.Add("CHEM", 50);
var group = new Dictionary<string, Dictionary<string, int>>();
group.Add("10", group10);
group.Add("11", group11);
group.Add("9", group9);
int v1 = group["10"]["MATH"]; // v1 = 30
int v2 = group["11"]["MATH"]; // v2 = 40
int v3 = group["9"]["CHEM"]; // v3 = 50
Option 2: Or create a compound key for the dictionary that overrides GetHashCode and Equals, or you could use Tuple.
var group = new Dictionary<Tuple<string, string>, int>();
group.Add(Tuple.Create("10", "MATH"), 30);
group.Add(Tuple.Create("11", "MATH"), 40);
group.Add(Tuple.Create("9", "CHEM"), 50);
int v1 = group[Tuple.Create("10", "MATH")]; // v1 = 30
int v2 = group[Tuple.Create("11", "MATH")]; // v2 = 40
int v3 = group[Tuple.Create("9", "CHEM")]; // v3 = 50
If using Option 1 you must remember to create the second level Dictionary<string, int>, before adding the integer values.
Something like this may be
Dictionary<string, Dictionary<string><int>> dict = new Dictionary<string, Dictionary<string><int>>();
You could also create your own dictionary:
public class GroupDict
{
const string Separator = ";";
Dictionary<string, int> _internalDict = new Dictionary<string, int>();
public void Add(string key1, string key2, int value)
{
_internalDict.Add(key1 + Separator + key2, value);
}
public int this[string key1, string key2]
{
get { return _internalDict[key1 + Separator + key2]; }
set { _internalDict[key1 + Separator + key2] = value; }
}
public int Count
{
get { return _internalDict.Count; }
}
}
You can then use it like:
GroupDict groups = new GroupDict();
groups.Add("10", "MATH", 30);
// OR
groups["10", "MATH"] = 30;
Console.WriteLine(groups["10", "MATH"]);
Also note that you can't create a Multi-Key Dictionary in C#.
You will need your own struct for that.

How to update the value stored in Dictionary in C#?

How to update value for a specific key in a dictionary Dictionary<string, int>?
Just point to the dictionary at given key and assign a new value:
myDictionary[myKey] = myNewValue;
It's possible by accessing the key as index
for example:
Dictionary<string, int> dictionary = new Dictionary<string, int>();
dictionary["test"] = 1;
dictionary["test"] += 1;
Console.WriteLine (dictionary["test"]); // will print 2
You can follow this approach:
void addOrUpdate(Dictionary<int, int> dic, int key, int newValue)
{
int val;
if (dic.TryGetValue(key, out val))
{
// yay, value exists!
dic[key] = val + newValue;
}
else
{
// darn, lets add the value
dic.Add(key, newValue);
}
}
The edge you get here is that you check and get the value of corresponding key in just 1 access to the dictionary.
If you use ContainsKey to check the existance and update the value using dic[key] = val + newValue; then you are accessing the dictionary twice.
Use LINQ: Access to dictionary for the key and change the value
Dictionary<string, int> dict = new Dictionary<string, int>();
dict = dict.ToDictionary(kvp => kvp.Key, kvp => kvp.Value + 1);
This simple check will do an upsert i.e update or create.
if(!dictionary.TryAdd(key, val))
{
dictionary[key] = val;
}
Here is a way to update by an index much like foo[x] = 9 where x is a key and 9 is the value
var views = new Dictionary<string, bool>();
foreach (var g in grantMasks)
{
string m = g.ToString();
for (int i = 0; i <= m.Length; i++)
{
views[views.ElementAt(i).Key] = m[i].Equals('1') ? true : false;
}
}
update - modify existent only. To avoid side effect of indexer use:
int val;
if (dic.TryGetValue(key, out val))
{
// key exist
dic[key] = val;
}
update or (add new if value doesn't exist in dic)
dic[key] = val;
for instance:
d["Two"] = 2; // adds to dictionary because "two" not already present
d["Two"] = 22; // updates dictionary because "two" is now present
This may work for you:
Scenario 1: primitive types
string keyToMatchInDict = "x";
int newValToAdd = 1;
Dictionary<string,int> dictToUpdate = new Dictionary<string,int>{"x",1};
if(!dictToUpdate.ContainsKey(keyToMatchInDict))
dictToUpdate.Add(keyToMatchInDict ,newValToAdd );
else
dictToUpdate[keyToMatchInDict] = newValToAdd; //or you can do operations such as ...dictToUpdate[keyToMatchInDict] += newValToAdd;
Scenario 2: The approach I used for a List as Value
int keyToMatch = 1;
AnyObject objInValueListToAdd = new AnyObject("something for the Ctor")
Dictionary<int,List<AnyObject> dictToUpdate = new Dictionary<int,List<AnyObject>(); //imagine this dict got initialized before with valid Keys and Values...
if(!dictToUpdate.ContainsKey(keyToMatch))
dictToUpdate.Add(keyToMatch,new List<AnyObject>{objInValueListToAdd});
else
dictToUpdate[keyToMatch] = objInValueListToAdd;
Hope it's useful for someone in need of help.
This extension method allows a match predicate delegate as the dictionary key selector, and a separate delegate to perform the dictionary value replacement, so it's completely open as to the type of key/value pair being used:
public static void UpdateAll<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, Func<TKey, TValue, bool> matchPredicate, Func<TValue, TValue> updatePredicate)
{
var keys = dictionary.Keys.Where(k => matchPredicate(k, dictionary[k])).ToList();
foreach (var key in keys)
{
dictionary[key] = updatePredicate(dictionary[key]);
}
}
Example usage:
Dictionary<int, string> dict = new Dictionary<int, string>();
dict.Add(1, "One");
dict.Add(2, "Two");
dict.Add(3, "Three");
//Before
foreach(var kvp in dict){
Console.WriteLine(kvp.Value);
}
dict.UpdateAll(
matchPredicate: (k, v) => k >= 2, //Update any dictionary value where the key is >= 2
updatePredicate: (v) => v = v + " is greater than One"
);
//After
foreach(var kvp in dict){
Console.WriteLine(kvp.Value);
}
You Can Also Use This Method :
Dictionary<int,int> myDic = new();
if (myDic.ContainsKey(1))
{
myDic[1] = 1234; // or use += to update it
}
Or By Value :
if (myDic.ContainsValue(1))
{
//do something ...
}

Categories