How to reverse the index in array of dictionaries? - c#

My array dictionary key value pairs are similar to this
[0]
key : x
value : 1
[1]
key : y
value : 2
[2]
key : z
value : 3
But I need to reverse the index of the dictionary. I need to convert the above dictionary to this :
[0]
key : z
value : 3
[1]
key : y
value : 2
[2]
key : x
value : 1
I tried Reverse() function. But it didn't work. I don't know how to achieve this. Can anyone help me with this ?
How can I achieve this ?

You shouldn't assume dictionaries are ordered. They aren't.
If you want to have an array that is ordered, you should use a SortedDictionary. You can also reverse the order in there if you want to. You should use a custom comparer for that (altered from here):
class DescendedStringComparer : IComparer<string>
{
public int Compare(string x, string y)
{
int ascendingResult = Comparer<string>.Default.Compare(x, y);
// turn the result around
return 0 - ascendingResult;
}
}
//
SortedDictionary<string, string> test
= new SortedDictionary<string, string>(new DescendedDateComparer());
You can iterate over it with foreach for example. The results will be ordered descending.

the function Enumerable.Reverse() returns an IEnumerable not an array. Did you forget to make the reversed sequence an array? The following worked for me:
class Program
{
static void Main(string[] args)
{
var dict = new Dictionary<string, int>();
dict.Add("x", 1);
dict.Add("y", 2);
dict.Add("z", 3);
var reversed = dict.ToArray().Reverse();
var reversedArray = reversed.ToArray();
Console.ReadKey();
}
}

I tried reverse method, it worked. Please see below images. I used VS 2013, .Net 4.5
Output generated

You should use SortedDictionary and pass a key on construction
public sealed class CompareReverse<T> : IComparer<T>
{
private readonly IComparer<T> original;
public CompareReverse(IComparer<T> original)
{
this.original = original;
}
public int Compare(T left, T right)
{
return original.Compare(right, left);
}
}
and in your main call
var mydictionary = new SortedDictionary<int, string>(
new CompareReverse<int>(Comparer<int>.Default));
for eg:-
var mydictionary = new SortedDictionary<int, string>(
new CompareReverse<int>(Comparer<int>.Default));
dictionary.add(1, "1");
dictionary.add(2, "2");
dictionary.add(3, "3");
dictionary.add(4, "4");

SortedDictionary sorts by key, not by value.
Here's a clean way to reverse the order of values in a Dictionary:
List<KeyValuePair<string, string>> srcList = aDictionary.ToList();
srcList.Sort(
delegate(KeyValuePair<string, string> firstPair,
KeyValuePair<string, string> nextPair)
{
return firstPair.Value.CompareTo(nextPair.Value);
}
);
Dictionary<string, string> outputDictionary = new Dictionary<string, string>();
int listCount = srcList.Count;
for(int i = 0; i < listCount; i++) {
int valueIndex = i + 1;
outputDictionary.Add(srcList[i].Key, srcList[valueIndex]);
}
If what you want as output is a List of KeyValuePairs rather than a Dictionary, you can replace the final 6 lines of code in my example with this:
List<KeyValuePair<string, string>> destList = new List<KeyValuePair<string, string>>();
int listCount = srcList.Count;
for(int i = 0; i < listCount; i++) {
int valueIndex = i + 1;
destList.Add(new KeyValuePair<string, string>(srcList[i].Key, srcList[valueIndex]));
}

You can do this :
for (var i = dictionary.Count - 1; i >= 0; i--)
dictionary.Values.ElementAt(i), dictionary.Keys.ElementAt(i);
EDIT : Go here -> how to iterate a dictionary<string,string> in reverse order(from last to first) in C#?

Related

how to swap keys into values and values into key in a dictionary

guys i want to swap the keys and values in dictionary
my dictionary loook like this
public static void Main(string[] args)
{
Dictionary<int,int> dic = new Dictionary<int,int>{{1,10}, {2, 20}, {3, 30}};
}
now iam printing the values form dictionary
foreach (KeyValuePair<int, int> kvp in dic)
{
Console.WriteLine("Key = {0}, Value = {1}", kvp.Key, kvp.Value);
Console.ReadKey();
}
in display i got this
Key = 1, Value = 10
Key = 2, Value = 20
Key = 3, Value = 30
i want to swap values between key and value.. after swapping the answer should be like this
Key = 10, Value = 1
Key = 20, Value = 2
Key = 30, Value = 3
i did lambda expression it changed but i need some other method to do..
Supposing the values are unique, this can work:
var dic = new Dictionary<int,int>{{1,10}, {2, 20}, {3, 30}};
var dic2 = dic.ToDictionary(x => x.Value, x=> x.Key);
It won't actually swap the sides, you will get a new dictionary.
Here is an extension so you can do:
Dictionary<int, int> newDic = oldDic.SwapKeysAndValues();
/// <summary>
/// Take a dictionary and make the values the keys and the keys the values
/// </summary>
/// <typeparam name="K">The original dictionary key type</typeparam>
/// <typeparam name="V">The original value type</typeparam>
/// <param value="dictionary<K, V>"></param>
/// <returns>Dictionary<V, K></returns>
public static Dictionary<V, K> SwapKeysAndValues<K, V>(this Dictionary<K, V> original)
{
Dictionary<V, K> result = new Dictionary<V, K>();
foreach (V value in original.Values.Distinct())
{
result.Add(value, original.First(x => x.Value.Equals(value)).Key);
}
// optional
//if(original.Count > result.Count)
//{
// throw new Exception("Duplicate value ignored ");
//}
return result;
}
I ran speed tests and found creating a new dictionary without specifying the capacity ran slower if there are more than a handful of items. In fact, at 1,000 items it was around 30% slower*. Also if the key and value are the same types, you might also want the same IEqualityComparer to be used in the opposite direction. Finally, if you have a duplicate value, an error will be thrown with the Linq version.
The version here is basically the same as the Linq version with the additions of using the same IEqualityComparer if possible, setting the initial capacity, and preventing potential duplicate errors:
var dic = new Dictionary<int, int>() { { 1, 10 }, { 2, 20 }, { 3, 30 } };
var dic2 = dic.ToDictionarySwapped();
Console.WriteLine(String.Join(",", dic.Select(i => i.Key + ":" + i.Value)));
Console.WriteLine(String.Join(",", dic2.Select(i => i.Key + ":" + i.Value)));
public static Dictionary<V, K> ToDictionarySwapped<K, V>(this Dictionary<K, V> original, bool useSameComparerIfPossible = true)
{
IEqualityComparer<V> comparer = null;
if (useSameComparerIfPossible && typeof(K) == typeof(V)) comparer = (IEqualityComparer<V>)original.Comparer;
var swapped = new Dictionary<V, K>(capacity: original.Count, comparer: comparer);
foreach (var item in original) swapped[item.Value] = item.Key;
return swapped;
}
the test I ran was a loop swapping a dictionary containing 1000 items, 1000 times. The test was repeated with both the capacity being set and the capacity not being set. My average time was around 65ms when the capacity was set, and around 95ms when it was not set. The test was run after being compiled for Release mode.
I think you will understand the below code:
namespace Swap
{
public class Class1
{
public SortedDictionary<string, string> names;
public void BeforeSwaping()
{
Console.WriteLine("Before Swapping: ");
Console.WriteLine();
names = new SortedDictionary<string, string>();
names.Add("Sonoo", "srinath");
names.Add("Perer", "mahesh");
names.Add("James", "ramesh");
names.Add("Ratan", "badri");
names.Add("Irfan", "suresh");
names.Add("sravan", "current");
foreach (KeyValuePair<string, string> item in names)
{
Console.WriteLine("Key: {0}, Value: {1}", item.Key, item.Value);
}
Console.WriteLine();
}
public void AfterSwaping()
{
Console.WriteLine("After Swapping: ");
Console.WriteLine();
var key = names.Keys;
var val = names.Values;
string[] arrayKey = new string[key.Count];
string[] arrayVal = new string[val.Count];
int i = 0;
foreach (string s in key)
{
arrayKey[i++] = s;
}
int j = 0;
foreach (string s in val)
{
arrayVal[j++] = s;
}
names.Clear();
//Console.WriteLine(arrayVal[0] + " " + arrayKey[0]);
for (int k = 0; k < (arrayKey.Length + arrayVal.Length) / 2; k++)
{
names.Add(arrayVal[k], arrayKey[k]);
}
foreach (KeyValuePair<string, string> s in names)
{
Console.WriteLine("key:"+s.Key + ", "+"value:" + s.Value);
}
}
public static void Main(string[] args)
{
Class1 c = new Class1();
c.BeforeSwaping();
c.AfterSwaping();
Console.ReadKey();
}
}
}

List of objects with a list as a property of the object

Declaring a list of objects:
List<object> result = new List<object>();
and a list of int to store the ids:
List<int> ids = new List<int>();
I want to store in result objects containing the pair (string, list of int).
It works fine for the pair (string, int) but I want that when there are 2 identical strings to have only one object and the int values to be stored in a list.
ex: {pars = "xxx", id = 1} , {pars = "xxx", id = 2} becomes {pars = "xxx", id = (1,2 )}
For doing the initial functionality, I use a foreach through an object from which I take the string(pars) and the id:
foreach (dataBinding in myData)
{
var x = string.Join(" ", dataBinding.Params.Select(p => p.myDescription));
result.Add(new { pars = x, id = dataBinding.Id });
}
there could be more strings in Params, that's why I use the join.
As it is here it works by creating objects having the form (string, int). But my aim is to make it (string, list of int) and if there are two objects with same string to combine them as I wrote before.
I tried to add ids list as the second property of the object but probably I'm not doing it correctly.
result.Add(new { pars = x, ids = dataBinding.Id });
You can use LINQ, especially GroupBy:
Dictionary<string, List<int>> descriptionIDs = myData
.GroupBy(x => x.myDescription)
.ToDictionary(g => g.Key, g => g.Select(x => x.Id).ToList());
Now you have even a dictionary, not just a strange List<object> that contains anonymous types.
As someone mentioned, you can also use ToLookup which i'd also prefer:
var descriptionLookup = myData.ToLookup(x => x.myDescription);
Now you can get the ID-List easily:
var result = descriptionLookup.Select(g => new { pars = g.Key, ids = g.Select(x=> x.Id).ToList() }).ToList():
Perhaps I am not understanding the scenario fully but I suspect using the following would server your purpose.
List<Dictionary<string, List<int>>>
When the key doesn't exist you add it and when it does you just add to the List.
Below program depicts the current generic collection type, also allow to add a new value if Key Already exists.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
MyProgram p = new MyProgram();
p.Add("First" , 5);
p.Add("Second" , 8);
p.Add("Third" , 9);
p.Add("First" , 6);
p.Add("First" , 7);
p.PrintDictionary();
}
}
public class MyProgram
{
private Dictionary<string, List<int>> dict = new Dictionary<string, List<int>>();
public void Add(string key, int value)
{
if (dict.ContainsKey(key))
{
dict[key].Add(value);
}
else
{
dict.Add(key, new List<int>() {value});
}
}
public void PrintDictionary()
{
foreach(var keyValue in dict)
{
Console.WriteLine("Key : " + keyValue.Key);
foreach(var val in keyValue.Value)
{
Console.WriteLine(string.Format("\t Value : {0}", val));
}
}
}
}
Output :
Key : First
Value : 5
Value : 6
Value : 7
Key : Second
Value : 8
Key : Third
Value : 9
Check this Live Fiddle.

Find closest value in a list in C# with linq?

I've a list like this:
public List<Dictionary<int, int>> blanks { get; set; }
This keep some index values:
In addition I have also a variable named X. X can take any value. I want to find closest 'Key' value to X. For example:
If X is 1300, I want to take blanks index: 2 and Key: 1200.
How can I do this via linq? Or, is there any other solution?
Thanks in advance.
EDIT: What if it is not a Dictionary. What if it is a List like this:
List<List<int[]>> lastList = new List<List<int[]>>();
This time, I want to take first List's indexes and second List's index. For example, if X is 800, I want to take 0 and 0 (for index 0) and also take 1 and 1 (for index 1) How can I do this time?
var diffs = blanks.SelectMany((item, index) => item.Select(entry => new
{
ListIndex = index, // Index of the parent dictionary in the list
Key = entry.Key, // Key
Diff = Math.Abs(entry.Key - X) // Diff between key and X
}));
var closestDiff = diffs.Aggregate((agg, item) => (item.Diff < agg.Diff) ? item : agg);
Dictionary<int, int> closestKeyDict = blanks[closestKey.ListIndex];
int closestKey = closestDiff.Key;
int closestKeyValue = closestKeyDict[closestKey];
The SelectMany clause flattens all the dictionaries entries into a collection of { ListIndex, DictionaryKey, Difference } instances.
This flattened collection is then aggregated to retrieve the item with the minimum difference.
To answer your second questsion:
var diffs = blanks.SelectMany((list, listIndex) => list.
SelectMany((array, arrayIndex) => array.
Select((item, itemIndex) => new
{
ListIndex = listIndex,
ArrayIndex = arrayIndex,
ItemIndex = itemIndex,
Diff = Math.Abs(item - X)
})));
var closestDiff = diffs.Aggregate((agg, item) => (item.Diff < agg.Diff) ? item : agg);
Now in closestDiff you'll find the indices of the closes item (List index, array index and array item index)
This might not be the most optimized way but it should just work,
List<Dictionary<int, int>> blanks = new List<Dictionary<int, int>>
{
new Dictionary<int, int>{{100,200}},
new Dictionary<int, int>{{500,200}},
new Dictionary<int, int>{{700,200}},
new Dictionary<int, int>{{1200,200}},
new Dictionary<int, int>{{300,200}},
new Dictionary<int, int>{{200,200}},
new Dictionary<int, int>{{800,200}},
};
int x = 1300;
IEnumerable<int> keys = blanks.SelectMany(ints => ints.Keys);
var diff = keys.Select(i => Math.Abs(i - x)).ToList();
var index = diff.IndexOf(diff.Min());
var value = blanks[index].Keys.First();

Dictionary<string, int> increase value

I have a Dictionary<string, int> and I am reading some strings from a list... I want to add them in the dictionary, but if the string is already in the dictionary, I want its value to increase by 1.
The code I tried is as below, but there are some strings that are increased with every input.. Is something wrong?
Dictionary<string, int> dictionary = new Dictionary<string, int>();
foreach (String recordline in tags)
{
String recordstag = recordline.Split('\t')[1];
String tagToDic = recordstag.Substring(0, (recordstag.Length-1) );
if (dictionary.ContainsKey(tagToDic) == false)
{
dictionary.Add(tagToDic, 1);
}
else
{
try
{
dictionary[tagToDic] = dictionary[tagToDic] + 1;
}
catch (KeyNotFoundException ex)
{
System.Console.WriteLine("X" + tagToDic + "X");
dictionary.Add(tagToDic, 1);
}
}
}
EDIT: To answer your comments... I am removing the last char of the string because it is always a blank space...
My input is like:
10000301 business 0 0,000
10000301 management & auxiliary services 0 0,000
10000316 demographie 0 0,000
10000316 histoire de france 0 0,000
10000347 economics 0 0,000
10000347 philosophy 1 0,500
and i want only the string like "business" or "management & auxiliary services" etc.
You are splitting each string in the input string array and selecting the 2nd string in the string array. Then you are removing the last character of this 2nd string using SubString. Hence all strings that differ only in the last character would be considered the same and incremented. Thats why you might be seeing "some strings that are increased with every input".
EDIT: If the purpose of removing the last char is to remove space, Use String.Trim instead.
Another edit is using TryGetValue instead of ContainsKey which performs better to increment your value. Code has been edited below.
Try this:
Dictionary<string, int> dictionary = new Dictionary<string, int>();
foreach(string recordline in tags)
{
string recordstag = recordline.Split('\t')[1].Trim();
int value;
if (!dictionary.TryGetValue(recordstag, out value))
dictionary.Add(recordstag, 1);
else
dictionary[recordstag] = value + 1;
}
No need for a dictionary, can be solved using this Linq query.
(Assuming you want the complete string after \t)
var q =
from s in tags.Select (t => t.Substring(t.IndexOf("\t")))
group s by s into g
select new
{
g.Key,
Count = g.Count()
};
And if you need it as a dictionary just add:
var dic = q.ToDictionary (x => x.Key, x => x.Count);
Your input string first split and then substring of it returned to tagToDic, So maybe n strings have a same tagToDic.
Extension method
public static void Increment(this Dictionary<string, int> dictionary, string key)
{
int val;
dictionary.TryGetValue(key, out val);
if (val != null)
dictionary[key] = val + 1;
}
Dictionary<string, int> dictionary = new Dictionary<string, int>();
// fill with some data
dictionary.Increment("someKey");
It's probably easier just to re-add the dictionary value after you retrieve the count from the existing one.
Here's some psuedo code to handle the look up logic.
Dictionary<string, int> _dictionary = new Dictionary<string, int>();
private void AdjustWordCount(string word)
{
int count;
bool success = _dictionary.TryGetValue(word, out count);
if (success)
{
//Remove it
_dictionary.Remove(word);
//Add it back in plus 1
_dictionary.Add(word, count + 1);
}
else //could not get, add it with a count of 1
{
_dictionary.Add(word, 1);
}
}
How about:
Dictionary<string, int> dictionary = new Dictionary<string, int>();
string delimitedTags = "some tab delimited string";
List<string> tags = delimitedTags.Split(new char[] {'\t'}, StringSplitOptions.None).ToList();
foreach (string tag in tags.Distinct())
{
dictionary.Add(tag, tags.Where(t => t == tag).Count());
}
If you have them in a list you could just group them and make your list.
list.GroupBy(recordline => recordline.Split('\t').Substring(0, (recordstag.Length-1),
(key, ienum) => new {word = key, count = ienum.Count()});
Then you can put that in a dictionary or iterate it or something.
Your dictionary code looks like it will function the way you expect.
My best guess is that your string-splitting code is not working correctly.
You'd have to give us some sample inputs to verify this though.
Anyway, your entire block of code could be simplified and rewritten with LINQ as:
var dictionary = tags
.Select(t => {
var recordstag = t.Split('\t')[1];
return recordstag.Substring(0, recordstag.Length-1);
})
.GroupBy(t => t)
.ToDictionary(k => k.Key, v => v.Count())
;

LINQ dictionary to jagged array?

There is a method that returns 2D array, this method querying a dictionary from LINQ query and trying to store keys and values in 2D array.
But I am not able to do that
public string[][] GetRecordFields(string selectedRecord)
{
var recordFields = (from record in _recordMasterList
where record.Item1 == selectedRecord
select new
{
record.Item2.Keys,
record.Item2.Values
}).ToArray();
return recordFields;
}
But its failed, is there any way?
EDIT:
Type of _recordMasterList
List<Tuple<string, Dictionary<string, string>>> _recordMasterList;
Create a string array instead of an object in the query, then the ToArray will return an array of arrays:
public string[][] GetRecordFields(string selectedRecord) {
return (
from record in _recordMasterList
where record.Item1 == selectedRecord
select new string[] {
record.Item2.Keys,
record.Item2.Values
}
).ToArray();
}
In your select you need to create a string array (new []). In your example you were creating a new anonymous type.
public string[][] GetRecordFields(string selectedRecord)
{
string[][] recordFields = (from record in _recordMasterList
where record.Key == selectedRecord
select new []
{
record.Key,
record.Value
}).ToArray();
return recordFields;
}
(I've changed the code slightly to deal with a _recordMasterList of type Dictionary<string, string>. Also, in code like this I find it clearer to declare my variable type explicitly, rather than relying on implicit typing. That said, with arrays I prefer to use implicit array typing - new [] rather than new string[].)
Not a one liner LINQ magic but here it is:
/// <summary>
/// Converts dictionary to 2d string array
/// </summary>
/// <param name="Dictionary">Dictionary to be converted</param>
/// <returns>2D string Array</returns>
private string[,] ConvertDictionaryTo2dStringArray(Dictionary<string, string> Dictionary)
{
string[,] stringArray2d = new string[2, Dictionary.Count];
int i = 0;
foreach (KeyValuePair<string, string> item in Dictionary)
{
stringArray2d[0, i] = item.Key;
stringArray2d[1, i] = item.Value;
i++;
}
return stringArray2d;
}
A more generic version with reversed dimensions:
private object[,] Dictionary2Array(Dictionary<object, object> dic)
{
object[,] arr = new object[dic.Count, 2];
int i = 0;
foreach (KeyValuePair<object, object> item in dic)
{
arr[i, 0] = item.Key;
arr[i, 1] = item.Value;
i++;
}
return arr;
}
Your question is still a little bit confussing. Is this the behaviour you are looking for?
(I know that this answer could be optimised a lot, but it seams the easiest way to figue out what you want.)
public string[,] GetRecordFields(string selectedRecord)
{
//List<Tuple<string, Dictionary<string, string>>> _recordMasterList;
List<Dictionary<string, string>> selectedRecords
= (from record in _recordMasterList
where record.Item1 == selectedRecord
select record.Item2)
.ToList();
int totalNumberOfRecords = 0;
foreach(Dictionary<string, string> d in selectedRecords)
{
totalNumberOfRecords += d.Count();
}
string[,] result = new string[2, totalNumberOfRecords];
int i = 0;
foreach(Dictionary<string, string> d in selectedRecords)
{
foreach(KeyValuePair<string, string> kvp in d)
{
result[0,i] = kvp.Key;
result[1,i] = kvp.Value;
ii++;
}
}
return result;
}

Categories

Resources