How to name dictionary/list with variable - c#

I get fed JSON data and I need to create a varying amount of dictionaries to store events in. I can't seem to figure out or find and answer to something like this:
Creating a Dictionary:
foreach (Identity x in List.Identities)
{
Dictionary<int, int> shop + x.Id = new Dictionary<int, int>();
Dictionary<int, int> de + x.Id = new Dictionary<int, int>();
Dictionary<int, int> sell + x.Id = new Dictionary<int, int>();
}
So that later I can also input the varying number of events with max efficiency:
foreach (Event x in y.events)
{
if ((x.Type.Contains("PURCHASED")){
shop+x.Id.Add(x.timestamp, x.item);
}
if ((x.Type.Contains("SOLD")){
sell+x.Id.Add(x.timestamp, x.item);
}
if ((x.Type.Contains("DESTROYED")){
de+x.Id.Add(x.timestamp, x.item);
}
}
I know this is definitely NOT the way to declare these, but I can't find a way to have an int variable declared in the dictionary name. If this works with lists, that would work as well, anything that I can foreach. Thanks!
Here's the classes to avoid confusion:
public class Event
{
public string Type { get; set; }
public int timestamp { get; set; }
public int item { get; set; }
public int Id { get; set; }
}
public class ParticipantIdentity
{
public int Id { get; set; }
}

You don't. Variable names in C# are never dynamic - it sounds like you want a map from ID to "dictionary of timestamp to item".
In fact, I would probably create a separate type of ItemEvents or something similar, which contained all the events for items with a single ID - e.g. by having three dictionaries within it.
You'd then just need:
var eventsByItem = List.Identities.GroupBy(x => x.Id)
.Select(g => new ItemEvents(g.Key, g))
.
where the ItemEvents constructor would do the splitting, e.g.
public ItemEvents(int id, IEnumerable<Event> events)
{
this.id = id;
shops = events.Where(e => e.Type.Contains("PURCHASED"))
.ToDictionary(e => e.timestamp, e => e.item);
// Ditto for the other dictionaries.
}
As an aside, I would try to use a more meaningful type than int for a timestamp - and consider using an enum for the event type.

You can create yet another set of dictionaries, with x.Id being a key:
Dictionary<int, Dictionary<int, int>> shops = Dictionary<int, Dictionary<int, int>>;
Dictionary<int, Dictionary<int, int>> des = Dictionary<int, Dictionary<int, int>>;
Dictionary<int, Dictionary<int, int>> sells = Dictionary<int, Dictionary<int, int>>;
So later you can do this:
foreach (Identity x in List.Identities)
{
shops[x.Id] = new Dictionary<int, int>();
...
}
and this:
if ((x.Type.Contains("PURCHASED")){
shops[x.Id].Add(x.timestamp, x.item);
}

What you are looking for is a dirctionary of dictionaries:
var shops = new Dictionary<int,Dictionary<int, int>>();
foreach (Identity x in List.Identities)
{
shops.Add(x.Id,new Dictionary<int, int>());
//des and shells the same way
}
and then
foreach (Event x in y.events)
{
if ((x.Type.Contains("PURCHASED")){
shops[x.Id].Add(x.timestamp, x.item);
}

As you know, you can't dynamically create variable names like that.
You could create a dictionary of dictionaries:
var dictionaries = new Dictionary<string, Dictionary<int, int>>();
foreach (Identity x in List.Identities)
{
dictionaries.add("shop" + x.Id, new Dictionary<int, int>());
dictionaries.add("de" + x.Id, new Dictionary<int, int>());
dictionaries.add("sell" + x.Id, new Dictionary<int, int>());
}
foreach (Event x in y.events)
{
if ((x.Type.Contains("PURCHASED")){
dictionaries["shop"+x.Id].Add(x.timestamp, x.item);
}
if ((x.Type.Contains("SOLD")){
dictionaries["sell"+x.Id].Add(x.timestamp, x.item);
}
if ((x.Type.Contains("DESTROYED")){
dictionaries["de"+x.Id].Add(x.timestamp, x.item);
}
}

Related

Splitting and ordering the class c#

I have a class like
Class Foo
{
public string info { get; set; };
public string name { get; set; }
}
Now, info is like :
id=2&pid=6
id=2&pid=6&cid=7
id=2
Now, I want to sort it based on the count of parameters (after spliting by &)
so, it should be
id=2&pid=6&cid=7
id=2&pid=6
id=2
But, I have a list of properties to a class.
The code I wrote is :
private List<Foo> FuncADesc(List<Foo> listObj)
{
Dictionary<string, int> di1 = new Dictionary<string, int>();
for (int i = 0; i < listObj.Count; i++)
{
Dictionary<string,string> diTemp = GetInfo(listObj[i].info);
if (diTemp != null)
{
di1.Add(listObj[i].info, diTemp.Count);
}
}
var list = di1.Keys.ToList();
list.Sort(); // I want to sort by Descending
for (int i = 0; i < list.Count; i++)
{
listObj[i].info = list[i];
listObj[i].name = // ??? //
}
return listObj;
}
//Gets the dictionary after splitting by '&'
private Dictionary<string, string> GetInfo(string Info)
{
Dictionary<string, string> dict1 = null;
if (!string.IsNullOrWhiteSpace(Info))
{
NameValueCollection parse1 = HttpUtility.ParseQueryString(Info);
dict1 = parse1.Cast<string>()
.Select(s => new {Key = s, Value = parse1[s]})
.ToDictionary(dictElement => dictElement.Key.ToLowerInvariant(),
dictElement => dictElement.Value.ToLowerInvariant());
}
return dict1;
}
I want to return listObj but the name and info gets exchange. Is there some easy way or can you point, where can I change ?
You should be able to use LINQ to do something as simple as this:
private List<Foo> FuncADesc(List<Foo> listObj)
{
return listObj.OrderByDescending(x => x.info.Count(c => c == '&')).ToList();
}
OrderByDescending allows you to order the items in a descending fashion. This method uses the number of & characters within the info property of each item as the sort by value.

How to get key value based on id from list of dictionaries?

This is my code
public class model
{
public model();
public List<Dictionary<string, string>> Data { get; set; }
}
List<Dictionary<string,string>> data1;
var data1 = await get<model>();
data1[0]=[0][{id,101}]
[1][{name,one}]
data1[1]=[0][{id,102}]
[1][{name,two}]
data1[2]=[0][{id,103}]
[1][{name,three}]
In the code i have a list of dictionaries with id and name keys. now i have id=102 search in list of dictionaries and get name value related on id using linq query.
var name = data1.First(d => d["id"] == "102")["name"];
You find the first list element where the key "id" maps to value "102", and then get the value for key "name".
Try this
List<Dictionary<string, string>> data1 = new List<Dictionary<string, string>>();
Dictionary<string, string> dic1 = new Dictionary<string, string>();
dic1.Add("101", "one");
dic1.Add("102", "two");
data1.Add(dic1);
dic1 = new Dictionary<string, string>();
dic1.Add("201", "2one");
dic1.Add("202", "2two");
data1.Add(dic1);
dic1 = new Dictionary<string, string>();
dic1.Add("301", "3one");
dic1.Add("302", "3two");
data1.Add(dic1);
//try your values here
var id = "201";
var s=data1.Where(c => c.Keys.Contains(id)).Select(c => c.Keys.Where(p => p == id).Select(p => c[p]).FirstOrDefault()).FirstOrDefault();
Console.WriteLine(s);

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.

Creating a multidimensional dictionary in C# for Windows Phone 7.8

I need to store daily statistics in the isolated storage of Windpws Phone which leads me to believe that a multidimensional dictionary would be the most useful but I'm having trouble wrapping my head around the logic needed to get this to work.
The stats looks something like this in pseudocode:
dictionary DailyStats {
1,
[Stats] => dictionary {
[Class] => 5,
[Entertainment] => 3,
[Personnel] => 2,
[Price] => 7,
[Quality] => 6
}
}
I started out with this:
var DailyStats = new Dictionary<int, Dictionary<string, string>>();
But as soon as I wanted to assign values to this structure I got lost quite fast. The values are collected by the app for each day.
I've thought of Linq but it seems to be overkill for what I'm trying to do.
Can anyone point me in the right direction?
Thanks!
If you have one dicionary with StatusClasses???
var DailyStats = new Dictionary<int, StatusClass>();
And:
class StatusClass
{
//substitute the vars for their type
var Class;
var Entertainment;
var Personnel;
var Price;
var Quality;
public StatusClass(var ClassValue, var EntertainmentValue, var Personnel.....)
{
Class = ClassValue;
Entertainment = EntertainmentValue;
...........
}
}
If your keys are fixed Daniel's solution is the way to go. If you want to use a dictionary a static class like this might help:
static class DailyStats
{
static Dictionary<int, Dictionary<string, string>> _dic;
static DailyStats()
{
_dic = new Dictionary<int, Dictionary<string, string>>();
}
public static void Add(int i, string key, string value)
{
if (!_dic.ContainsKey(i))
_dic[i] = new Dictionary<string, string>();
_dic[i][key] = value;
}
public static string Get(int i, string key)
{
if (!_dic.ContainsKey(i) || !_dic[i].ContainsKey(key))
return null;
return _dic[i][key];
}
}
DailyStats.Add(1, "Stats", "a");
Console.WriteLine(DailyStats.Get(1, "Stats"));

copy dictionary containing object to an array of objects 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();

Categories