Convert Generic Dictionary to different type - c#

Is there a quick way to convert a Generic Dictionary from one type to another
I have this
IDictionary<string, string> _commands;
and need to pass it to a function that takes a slightly different typed Dictionary
public void Handle(IDictionary<string, Object> _commands);

I suppose I would write
Handle(_commands.ToDictionary(p => p.Key, p => (object)p.Value));
Not the most efficient thing in the world to do, but until covariance is in, that's the breaks.

maybe this function can be useful for you
IEnumerable<KeyValuePair<string, object>> Convert(IDictionary<string, string> dic) {
foreach(var item in dic) {
yield return new KeyValuePair<string, object>(item.Key, item.Value);
}
}
And you will call it like so:
Handle(Convert(_commands));

could something like this do?
Dictionary<int, string> dict = new Dictionary<int, string>();
dict.Add(1, "One");
dict.Add(2, "Two");
dict.Add(3, "Three");
dict.Add(4, "Four");
dict.Add(5, "Five");
object dictObj = (object)dict;
IDictionary temp = (IDictionary)dictObj;
Dictionary<int, object> objs = new Dictionary<int, object>();
foreach (DictionaryEntry de in temp)
{
objs.Add((int)de.Key, (object)de.Value);
}

Can't you use
Dim myDictionary AS New Dictionary(Of Object, Object)
This would then be able to accept any types

Related

Converting Dictionary<Int, Object> To Dictionary<Int, Object.Property> with lambdas

Suppose I have a class Building with properties int Id, int Height, int NumberOfFloors.
If I have a Dictionary, where each key is the building id. Is there a way to convert this into a Dictionary where each key is the building Id, and each value is the number of floors. Obviously this is feasible with a loop. Just wondering if there is a simple way to do this using lambdas?
Thanks!
var intToBuilding = new Dictionary<int, Building>(); //pretend populated
var intToInt = new Dictionary<int, int>();
foreach(var intBuilding in intToBuilding)
{
var building = userPreference.Value;
intToInt.Add(intBuilding.Key, building.Height);
}
It should go something like:
var floorDictionary = buildingDictionary
.ToDictionary(kv => kv.Key, kv => kv.Value.NumberofFloors);
The source dictionary implements IEnumerable< KeyValuePair<TKey, TValue> > and for that there is an extension method ToDictionary(keySelector, valueSelector).

Creating Dictionary<string, Dictionary<T, T[]>[]>

In C#, what is the syntax for instantiating and initializing a dictionary containing as values an array of dictionaries, those dictionaries themselves containing arrays as values?
For example, (I believe),
Dictionary<string, Dictionary<string, string[]>[]>?
Here's an example of what I'm trying to do:
private static readonly Dictionary<string, Dictionary<string, DirectoryInfo[]>[]> OrderTypeToFulfillmentDict = new Dictionary<string, Dictionary<string, DirectoryInfo[]>>()
{
{"Type1", new []
{
ProductsInfo.Type1FulfillmentNoSurfacesLocations,
ProductsInfo.Type2FulfillmentSurfacesLocations
}
}
}
where Type1Fulfillment..., and Type2Fulfillment... are already constructed as
Dictionary<string, DirectoryInfo[]>.
This throws the following compiler error:
"Cannot convert from System.Collections.Generic.Dictionary<string, System.IO.DirectoryInfo[]>[] to System.Collections.Generic.Dictionary<string, System.IO.DirectoryInfo[]>"
Edit: The problem was, as Lanorkin pointed out, that I was missing the final [] in the new Dictionary<string, Dictionary<string, DirectoryInfo[]>>(). Still, it goes without saying that this probably isn't something anyone should be trying to do in the first place.
What you've got looks correct, but what you're doing has a real code smell about it that's going to lead to some serious technical debt.
For starters, rather than having an inner Dictionary<string, string[]> model this in a class with methods appropriate to what you're trying to model. Otherwise anyone accessing this type isn't going to have a clue about what it's really modeling.
Something like this:
var dic = new Dictionary<string, Dictionary<int, int[]>[]>
{
{
"key1",
new[]
{
new Dictionary<int, int[]>
{
{1, new[] {1, 2, 3, 4}}
}
}}
};
Dictionary<string, Dictionary<string, string[]>[]> complexDictionary = new Dictionary<string, Dictionary<string, string[]>[]>();
or using the var keyword:
var complexDictionary = new Dictionary<string, Dictionary<string, string[]>[]>();
The following is perfectly valid
// array of dictionary
Dictionary<int, string[]>[] matrix = new Dictionary<int, string[]>[4];
//Dictionary of string and dictionary array
Dictionary<string, Dictionary<string, string[]>[]> dicOfArrays= new Dictionary<string, Dictionary<string, string[]>[]>();
private static readonly Dictionary<string, Dictionary<string, DirectoryInfo[]>>
OrderTypeToFulfillmentDict = new Dictionary<string, Dictionary<string, DirectoryInfo[]>>()
{
{"Type1", new []
{
ProductsInfo.Type1FulfillmentNoSurfacesLocations,
ProductsInfo.Type2FulfillmentSurfacesLocations
}
}
}
You have the wrong type in your variable definition. Remove the final "[]" as you don't want an array of dictionaries.

define a List like List<int,string>?

I need a two column list like:
List<int,string> mylist= new List<int,string>();
it says
using the generic type System.collection.generic.List<T> requires 1 type arguments.
Depending on your needs, you have a few options here.
If you don't need to do key/value lookups and want to stick with a List<>, you can make use of Tuple<int, string>:
List<Tuple<int, string>> mylist = new List<Tuple<int, string>>();
// add an item
mylist.Add(new Tuple<int, string>(someInt, someString));
If you do want key/value lookups, you could move towards a Dictionary<int, string>:
Dictionary<int, string> mydict = new Dictionary<int, string>();
// add an item
mydict.Add(someInt, someString);
You could use an immutable struct
public struct Data
{
public Data(int intValue, string strValue)
{
IntegerData = intValue;
StringData = strValue;
}
public int IntegerData { get; private set; }
public string StringData { get; private set; }
}
var list = new List<Data>();
Or a KeyValuePair<int, string>
using Data = System.Collections.Generic.KeyValuePair<int, string>
...
var list = new List<Data>();
list.Add(new Data(12345, "56789"));
With the new ValueTuple from C# 7 (VS 2017 and above), there is a new solution:
List<(int,string)> mylist= new List<(int,string)>();
Which creates a list of ValueTuple type. If you're targeting .NET Framework 4.7+ or .NET/.NET Core, it's native, otherwise you have to get the ValueTuple package from nuget.
It's a struct opposing to Tuple, which is a class. It also has the advantage over the Tuple class that you could create a named tuple, like this:
var mylist = new List<(int myInt, string myString)>();
That way you can access like mylist[0].myInt and mylist[0].myString
Since your example uses a generic List, I assume you don't need an index or unique constraint on your data. A List may contain duplicate values. If you want to insure a unique key, consider using a Dictionary<TKey, TValue>().
var list = new List<Tuple<int,string>>();
list.Add(Tuple.Create(1, "Andy"));
list.Add(Tuple.Create(1, "John"));
list.Add(Tuple.Create(3, "Sally"));
foreach (var item in list)
{
Console.WriteLine(item.Item1.ToString());
Console.WriteLine(item.Item2);
}
Use C# Dictionary datastructure it good for you...
Dictionary<string, int> dict = new Dictionary<string, int>();
dict.Add("one", 1);
dict.Add("two", 2);
You can retrieve data from Ditionary in a simple way..
foreach (KeyValuePair<string, int> pair in dict)
{
MessageBox.Show(pair.Key.ToString ()+ " - " + pair.Value.ToString () );
}
For more example using C# Dictionary... C# Dictionary
Navi.
Not sure about your specific scenario, but you have three options:
1.) use Dictionary<..,..>
2.) create a wrapper class around your values and then you can use List
3.) use Tuple
List<Tuple<string, DateTime, string>> mylist = new List<Tuple<string, DateTime,string>>();
mylist.Add(new Tuple<string, DateTime, string>(Datei_Info.Dateiname, Datei_Info.Datum, Datei_Info.Größe));
for (int i = 0; i < mylist.Count; i++)
{
Console.WriteLine(mylist[i]);
}
For that, you could use a Dictionary where the int is the key.
new Dictionary<int, string>();
If you really want to use a list, it could be a List<Tuple<int,string>>() but, Tuple class is readonly, so you have to recreate the instance to modifie it.

Finding already existing value in Key Value pair

I am storing a string and int value in Key value pair.
var list = new List<KeyValuePair<string, int>>();
While adding i need to check if string(Key) already exists in list, if exists i need to add it to Value instead of adding new key.
How to check and add?
Instead of List you can use Dictionary and check if it contains key then add the new value to the existing key
int newValue = 10;
Dictionary<string, int> dictionary = new Dictionary<string, int>();
if (dictionary.ContainsKey("key"))
dictionary["key"] = dictionary["key"] + newValue;
use dictonary. Dictionary in C# and I suggest you to read this post Dictonary in .net
Dictionary<string, int> dictionary =
new Dictionary<string, int>();
dictionary.Add("cat", 2);
dictionary.Add("dog", 1);
dictionary.Add("llama", 0);
dictionary.Add("iguana", -1);
to check. use ContainsKey ContainsKey
if (dictionary.ContainsKey("key"))
    dictionary["key"] = dictionary["key"] + yourValue;
If you need use the list,you must foreach the list,and look for the keys.
Simplely,you can use hashtable.
For anyone who has to use a List (which was the case for me, since it does things Dictionary doesn't), you can just use a lambda expression to see if the List contains the Key:
list.Any(l => l.Key == checkForKey);
Your needs exactly describe the design of Dictionarys?
Dictionary<string, string> openWith =
new Dictionary<string, string>();
// Add some elements to the dictionary. There are no
// duplicate keys, but some of the values are duplicates.
openWith.Add("txt", "notepad.exe");
// If a key does not exist, setting the indexer for that key
// adds a new key/value pair.
openWith["doc"] = "winword.exe";
For sure, dictionary is preferable in your case. You can not modify the Value of KeyValue<string,int> class as it is Immutable.
But even if you still want to use List<KeyValuePair<string, int>>();. You can use IEqualityComparer<KeyValuePair<string, int>>. Code will be like.
public class KeyComparer : IEqualityComparer<KeyValuePair<string, int>>
{
public bool Equals(KeyValuePair<string, int> x, KeyValuePair<string, int> y)
{
return x.Key.Equals(y.Key);
}
public int GetHashCode(KeyValuePair<string, int> obj)
{
return obj.Key.GetHashCode();
}
}
And use it in Contains like
var list = new List<KeyValuePair<string, int>>();
string checkKey = "my string";
if (list.Contains(new KeyValuePair<string, int>(checkKey, int.MinValue), new KeyComparer()))
{
KeyValuePair<string, int> item = list.Find((lItem) => lItem.Key.Equals(checkKey));
list.Remove(item);
list.Add(new KeyValuePair<string, int>("checkKey", int.MinValue));// add new value
}
which does not sounds good way.
hope this info helps..

using dictionary as a key in other dictionary

I would like to use Dictionary as TKey in another Dictionary. Something similar to python. I tried this but it gives me errors.
Dictionary<Dictionary<string, string>, int> dict = new Dictionary<Dictionary<string, string>, int>();
Dictionary<string, string> dict2 = new Dictionary<string, string>();
dict2["abc"] = "def";
dict[dict["abc"] = 20;
What error is it giving you? Is it complaining about your missing bracket on line 4?
Line 4 looks like it should be:
dict[dict["abc"]] = 20;
However, you probably mean this, since "abc" is not a key of dict:
dict[dict2["abc"]] = 20;
But dict2["abc"] is a string, when the key of dict is supposed to be a Dictionary<string, string>.
But let's re-examine your original goal at this point before going to far down this path. You shouldn't be using mutable types as dictionary keys in the first place.
This may be the code you're looking for:
Dictionary<string, int> dict = new Dictionary<string, int>();
Dictionary<string, string> dict2 = new Dictionary<string, string>();
dict2["abc"] = "def";
dict[dict2["abc"]] = 20;
But it's hard to tell for sure.
Just to throw this in there, I often find that dealing with complicated dictionaries like you describe it's far better to use real names with them rather than trying to let the reader of the code sort it out.
You can do this one of two ways depending on personal preference. Either with a using statement to create a complier alias. Note you have to use the fully qualified type name since this is a compiler alias.
using ComplexKey = System.Collections.Generic.Dictionary<String, String>;
using ComplexType = System.Collections.Generic.Dictionary<
System.Collections.Generic.Dictionary<String, String>,
String
>;
Or you can go the full blown type way and actually create a class that inherits from Dictionary.
class ComplexKey : Dictionary<String, String> { ... }
class ComplexType : Dictionary<ComplexKey, String> { ... }
Doing this will make it far easier for both you and the reader of your code to figure out what you're doing. My general rule of thumb is if I'm creating a generic of a generic it's time to look at building some first class citizens to represent my logic rather.
It's because the "dict["abc"] is not dictionary, but "string".
The correct, what you asked is:
Dictionary<Dictionary<string, string>, int> dict = new Dictionary<Dictionary<string, string>, int>();
Dictionary<string, string> dict2 = new Dictionary<string, string>();
dict2["abc"] = "def";
dict[dict2] = 20;
But i'm not sure, this is what you realy want/need.

Categories