copy dictionary containing object to an array of objects c# - c#

I have a Dictionary like Dictionary<string,Object>,is there any method of converting the Dictionary to an array of objects,where the class of the object will contain two members-one of which will be the string and the other will be the Object stored as the value-pair in the dictionary.Please help!!!..

Dictionary<TKey, TValue> implements IEnumerable<T> where T is KeyValuePair<TKey, TValue>. To flatten this to an array all that is necessary is to call IEnuemrable<T>.ToArray as such:
Dictionary<string, int> dict = new Dictionary<string, int>() { { "Key1", 0 }, { "Key2", 1 } };
var kvArray = dict.ToArray();
kvArray will then be an array objects that reference the keys and values of each element in dict as two separate members of the same object.
Your question is a bit ambiguous though, perhaps further explanation would help us figure out a more appropriate solution.
Re your comment, LINQ is good for that:
Dictionary<string, int[]> dict = new Dictionary<string, int[]>() { { "Key1", new int[] { 0, 1, 2 } }, { "Key2", new int[] { 4, 5, 6 } } };
var pairs = dict.SelectMany(pair => pair.Value
.Select(v =>
new {
Key = pair.Key,
Value = v
}
)
);

Given a class:
class ClassA
{
string CustomerId { get; set; }
PatientRecords[] Records { get; set; }
public ClassA(string name, PatientRecords[] records)
{
Name = name;
Records = records;
}
}
I'm assuming that CollectionOfPatientRecords implements IEnumberable:
var dict = new Dictionary<string, CollectionOfPatientRecords> ( ... );
Then to get your array of ClassA with the right values:
dict.Select(kv => new ClassA(kv.Key, kv.Value.ToArray())).ToArray();

Related

Adding to reflected Dictionaries

I have a legacy class that looks like this:
public class LegacyBusinessObject
{
....(100 similar fields in total)
public Dictionary<string, string> SomeBusinessValue1 = new Dictionary<string, string>();
public Dictionary<string, long> SomeBusinessValue2 = new Dictionary<string, long>();
public Dictionary<string, decimal> SomeBusinessValue3 = new Dictionary<string, decimal>();
....
}
whereas the string key denominates the provider this value came from.
So for context: "SomeBusinessValue1" could be a weight measurement, that differs depending on the lab that did it.
I want to merge several of these monsters into one object using reflection:
public LegacyBusinessObject Merge(Dictionary<string, LegacyBusinessObject> objects)
{
var result = new LegacyBusinessObject();
//Loop through all the business object's fields
foreach (var prop in typeof(LegacyBusinessObject).GetFields())
{
//Second loop through all the individual objects from different providers
foreach (var ep in objects)
{
//Here I would need to test for all possivle value types that could
//be in the dictionary: <string, string>, <string, long>...
//then cast to it and invoke the Add method like this:
var propDictionary = prop.GetValue(result) as Dictionary<string, string>;
propDictionary.Add(ep.Key, ep.Value);
}
}
return result;
}
Now this approach requires me to do a lot of clumsy casts for propDictionary. (I also tried consctructing the matching keyvaluepair<,> and an Activator to instance it; but i can't find a way to add this to another dictionary)
Can you think of a better way to perform this merge, that takes arbitrary dictionary value types?
Some more context:
I am getting a LegacyBusinessObject Obj1 with data from Lab A and Lab B that is stored in the dictionaries. No I am cleaning up the database and find out that another LegacyBusinessObject Obj2 has Data from Lab C and Lab D. As it turns out there was a mistake during ingestion and Obj1 and Obj2 are for the same product and have wrongfully been stored in two different LegacyBusinessObjects. I now want to merge the data to get a new LegacyBusinessObject with Data from Lab A through D
Quite unclear what you are exactly asking, but:
public static LegacyBusinessObject Merge(Dictionary<string, LegacyBusinessObject> objects)
{
var result = new LegacyBusinessObject();
foreach (var prop in typeof(LegacyBusinessObject).GetFields())
{
var propDictionaryNew = (IDictionary)prop.GetValue(result);
foreach (var dict in objects)
{
var propDictionaryOld = (IDictionary)prop.GetValue(dict.Value);
foreach (DictionaryEntry de in propDictionaryOld)
{
propDictionaryNew[de.Key] = de.Value;
// Or:
//((IDictionary)result).Add(de.Key, de.Value);
// But be aware of exceptions if de.Key is present in multiple dictionaries
}
}
}
return result;
}
and then, to test it:
var lbo1 = new LegacyBusinessObject
{
SomeBusinessValue1 = new Dictionary<string, string> { { "A1", "A2" }, { "B1", "B2" } },
SomeBusinessValue2 = new Dictionary<string, long> { { "C1", 1 }, { "D1", 2 } },
SomeBusinessValue3 = new Dictionary<string, decimal> { { "E1", 3 }, { "F1", 4 } },
};
var lbo2 = new LegacyBusinessObject
{
SomeBusinessValue1 = new Dictionary<string, string> { { "G1", "G2" }, { "H1", "H2" } },
SomeBusinessValue2 = new Dictionary<string, long> { { "I1", 5 }, { "J1", 6 } },
SomeBusinessValue3 = new Dictionary<string, decimal> { { "K1", 7 }, { "L1", 8 } },
};
var result = Merge(new Dictionary<string, LegacyBusinessObject> { { "X", lbo1 }, { "Y", lbo2 } });
I'm cheating a little here... Dictionary<,> implements the pre-generics interface IDictionary (that is different from IDictionary<,>) that uses object as key and value. In this way I don't have to support the different value types. When using reflection with generic collections, a good trick is to see if the non-generic interfaces are enough to do what you need (because they are much easier to handle with reflection).

LINQ creating a new anonymous type when selecting a property that is a dictionary

I have a Simple POCO like this:
[JsonObject(NamingStrategyType = typeof (CamelCaseNamingStrategy))]
public class MyType
{
public string Id { get; set; }
public string Name;
[JsonExtensionData(ReadData = true, WriteData = true)]
public IDictionary<string, object> TypeDetails { get; set; }
}
and a method that gives me a list of MyType
i'm trying to return a list of Dictionary<string,object> with all the TypeDetails of the object list i got.
like this:
types.Select((myType) => myType.TypeDetails)
however, when i run this, what i get is a list of Dictionaries, but with the following shape:
[
{TypeDetails: {the dictionary i want},
{TypeDetails: {the dictionary i want}},
(...)
]
what i was expecting:
[
{the dictionary i want},
{the dictionary i want},
(...)
]
to clarify: i'd like this to be true:
types[0].TypeDetails.equals(r[0])
It's the same as if i were doing
types.Select((myType) => new {myType.TypeDetails})
if i get any other property the select behaves as i expected it.
i can't find any doc that indicates whether dictionaries get a special treatment, nor any other clue about why this is happening.
Use .SelectMany() on the Dictionary's values, like so:
types.SelectMany((myType) => myType.TypeDetails.Values)
Either your return expectation/description is out:
i'm trying to return a list of Dictionary<string,Object>
or, (assuming (myType) is of type MyType), your real code does not match:
types.Select((myType) => myType.TypeDetails)
The example code below does return a collection of Dictionary<string,Object>, it'd be interesting to see where your code differs from it:
var data = new[]
{
new MyType()
{
TypeDetails = new Dictionary<string, object>() { { "foo", "bar" } }
},
new MyType()
{
TypeDetails = new Dictionary<string, object>() { { "baz", "qux" } }
},
};
var r = data.Select(d => d.TypeDetails);

find all data from dictionary collection value to another dictionary collection key

I have dictionary collection
{key -> string, value -> class}
and I have another dictionary collection
{key -> string, value -> string}
note : 2nd dictionary collection {key -> string, value -> string}.Value is 1st dictionary collection {key -> string, value -> class}.Key
So, I have To find All Data From 1st dictionary collection according to 2nd collection value.
class MyTest
{
public int myValue { get; set; }
}
Main()
{
Dictionary<string, string> First = new Dictionary<string, string>();
First.Add("dd", "test");
First.Add("ss", "test");
First.Add("tt", "test");
First.Add("aa", "test");
First.Add("mm", "test");
Dictionary<string, MyTest> Second = new Dictionary<string, MyTest>();
Second.Add("dd", new MyTest() { myValue = 123 });
Second.Add("oo", new MyTest() { myValue = 123 });
Second.Add("tt", new MyTest() { myValue = 123 });
Second.Add("aa", new MyTest() { myValue = 123 });
Second.Add("rr", new MyTest() { myValue = 123 });
var Final1 = First.Where(S => Second.Any(T => S.Key.Equals(T.Key)));
var Final2 = Second.Where(S => First.Any(T => S.Key.Equals(T.Key)));
Console.WriteLine("\nFirst\n");
foreach (var item in Final1)
{
Console.WriteLine(item.Key + "-" + item.Value);
}
Console.WriteLine("\nSecond\n");
foreach (var item in Final2)
{
Console.WriteLine(item.Key + "-" + item.Value.myValue);
}
}
From my understanding of your question you want to lookup the first dictionary based on a second dictionaries value.
public class Test
{
public string MyValue {get;set;}
}
Dictionary<string, Test> DictOne = new Dictionary<string, Test>();
Dictionary<string, string> DictTwo = new Dictionary<string, string>();
DictOne.Add("DictOneKeyOne", new Test() { MyValue = "DictOneValueOne" } );
DictTwo.Add("DictTwoKeyOne", "DictOneKeyOne");
Test ValueFromDictOne = DictOne.ContainsKey(DictTwo["DictTwoKeyOne"]) ? DictOne[DictTwo["DictTwoKeyOne"]] : null;

Serialize some string values in a Dictionary as integers

Currently my Dictionary<string, string> is serialized as:
{
"Uri" : "/site/Default.aspx",
"time-taken" : "232"
}
I would like Json.net to serialize it as
{
"Uri" : "/site/Default.aspx",
"time-taken" : 232
}
What would be the easiest way to achieve this with Json.net? I don't want to make a new class with the correct types instead of the Dictionary since the keys are many and may change. I know the keys that will be int.
I think I would just make a helper method that copied the data from a dictionary to a JObject like this:
public static class JsonHelper
{
public static string SerializeDictionary(Dictionary<string, string> dict, IEnumerable<string> intKeys)
{
JObject obj = new JObject();
foreach (var kvp in dict)
{
int intValue;
if (intKeys.Contains(kvp.Key) && int.TryParse(kvp.Value, out intValue))
obj.Add(kvp.Key, intValue);
else
obj.Add(kvp.Key, kvp.Value);
}
return obj.ToString(Formatting.Indented);
}
}
Then use it like this:
var dict = new Dictionary<string, string>();
dict.Add("AnInt", "123");
dict.Add("AString", "abc");
dict.Add("AnotherInt", "456");
dict.Add("KeepThisAsString", "789");
dict.Add("NotAnInt", "xyz");
var intKeys = new string[] { "AnInt", "AnotherInt" };
string json = JsonHelper.SerializeDictionary(dict, intKeys);
Console.WriteLine(json);
Output:
{
"AnInt": 123,
"AString": "abc",
"AnotherInt": 456,
"KeepThisAsString": "789",
"NotAnInt": "xyz"
}
Fiddle: https://dotnetfiddle.net/xdnnb0

Sorting a list of dictionaries based on a key

I have a list of dictionaries which contains student data
It is something like
List<Dictionary<string, object>> students = new List<Dictionary<string, object>>();
Dictionary<string, object> std1 = new Dictionary<string, object>();
std1["name"] = "sai";
std1["age"] = 22;
std1["gender"] = "male";
students.Add(std1);
Dictionary<string, object> std2 = new Dictionary<string, object>();
std2["name"] = "Julia";
std2["gender"] = "female";
students.Add(std2);
Dictionary<string, object> std3 = new Dictionary<string, object>();
std3 ["name"] = "sunny";
std3 ["age"] = 23;
students.Add(std3);
And I want to sort the list of students based on either name, age or gender, I am trying something like this:
var ordered = students.OrderBy(x => x["name"]);
If I try with either age or gender it is returning an error that key is not found, as std2 doesn't have age and std3 doesn't have gender.
I need all the records even it doesn't contain the value for sorted key, Any way to solve this problem, Thanks in advance.
It is better to create a class like this:
public class YourClass
{
public string Name { get; set; }
public int Age { get; set; }
public string Gender { get; set; }
}
Then:
List<YourClass> students = new List<YourClass>();
YourClass std1 = new YourClass();
std1.Name = "sai";
std1.Age = 22;
std1.Gender = "male";
students.Add(std1);
yourClass std2 = new yourClass();
std2.Name = "Julia";
std2.Gender = "female";
students.Add(std2);
yourClass std3 = new yourClass();
std3.Name = "sunny";
std3.Age = 23;
students.Add(std3);
var ordered = students.OrderBy(x => x.Name);
This arrangement stores the same data you had in multiple dictionaries. However, it's far more clear and understandable.
If you want to sort by a key that is not present in all of the dictionaries, you'll need to return a default value instead, for example 0.
var ordered = students.OrderBy(dict =>
{
string name;
if (!dict.TryGetValue("name", out name))
return "";
return name;
});
Shorter version using the conditional ternary operator:
var ordered = students.OrderBy(dict =>
{
string name;
return dict.TryGetValue("name", out name) ? name : 0;
});
I use Dictionary.TryGetValue(...) which returns a bool depicting whether the key was found in the dictionary and its value returned.
You can solve this problem by supplying a GetOptional method that returns some default object in situations when the dictionary does not have a specific key:
V GetOptional<K,V>(IDictionary<K,V> d, K key, V absent) {
V res;
return d.TryGetValue(key, out res) ? res : absent;
}
Now you can sort like this:
var byName = students.OrderBy(x => GetOptional<string,object>(x, "name", "----"));
var byAge = students.OrderBy(x => GetOptional<string,object>(x, "age", "10000"));
Note: Using dictionaries like this gives you flexibility at the expense of clarity. It is usually better to define a special Student type, rather than using a universal collection of key-value pairs.

Categories