Creating a multidimensional dictionary in C# for Windows Phone 7.8 - c#

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"));

Related

C# - Short way to create List<KeyValuePair>> as parameter for method

I'm pretty sure there's a simple solution to my problem. However I'm not able to find it
Let's say I have a method which is defined as follows:
public bool Insert(string table, List<KeyValuePair<string, string>> fields) { }
Right now, I'm calling the function like this:
db.Insert("personen", new List<KeyValuePair<string, string>> {
new KeyValuePair<string, string>("firstname", "Dominic") });
Is there a way to shorten this infinitely long line?
Just to be clear, I mean this part of the call:
new List<KeyValuePair<string, string>> {
new KeyValuePair<string, string>("firstname", "Dominic") }
In C++, for example, you could/would do it this way:
db.Insert("personen", {{"firstname", "Dominic"}});
This would be much better with several values:
db.Insert("personen", {
{ "firstname", "Test" },
{ "lastname", "Test 2" },
{ "address", "Teest" }
});
C# version: v4.0.30319
.Net version: 4.6.1
I think a mix of static factories and params is as close as you are going to get:
static bool Insert(string table, params KeyValuePair<string, string>[] fields) {...}
class KeyValueFactory
{
public static KeyValuePair<TKey, TValue> of<TKey, TValue>(TKey key, TValue value)
{
return new KeyValuePair<TKey, TValue>(key, value);
}
}
Example usage:
Insert(
"personen",
KeyValueFactory.of("firstname", "Dominic"),
KeyValueFactory.of("lastName", "test2"));
This implemetation proofs you can use a using <symbol>=<type>; clause to reduce clutter without much impact on the rest of your code. You only need the lines with a // $$$ comment, the rest is just red tape to get things going. This compiles and runs on v4.x:
using System.Collections.Generic;
using K = System.Collections.Generic.KeyValuePair<string, string>; // $$$
public class MainClass
{
public static void Main(string[] args)
{
DBClass db;
db = new DBClass();
db.Insert("personen", new List<K> { // $$$
new K("firstname", "Dominic") // $$$
});
}
}
public class DBClass
{
public bool Insert(string name, List<KeyValuePair<string, string>> values)
{
// ...
return false;
}
}
The lightest version would be as follows, but it requires some help on the db side. This reduces clutter completely as you can see in the Insert() invocation:
using System.Collections.Generic;
public class MainClass
{
public static void Main(string[] args)
{
DBClass db;
db = new DBClass();
db.Insert("personen",
"firstname", "Dominic",
"lastname", "Cinimod"
);
}
}
public class DBClass
{
public bool Insert(string name, params string[] values)
{
if (values.Length % 2 == 1)
{
throw new System.ArgumentException("wrong number of arguments");
}
// ...
}
}
I want to be a little more clear about the second solution because it is highly controversial. After the parity check you should package the values in KVPs:
if (values.Length % 2 == 1)
{
throw new System.ArgumentException("wrong number of arguments");
}
KVPs = new List<KeyValuePairs<string, string>>();
for (i = 0; i < values.Length; i += 2)
{
KVPs.Add(new KeyValuePair<string, string>(values[i], values[i + 1]));
}
With this done, just delegate to the original method:
return this.Insert(name, KVPs); // pass on the returned bool!
By having both overloads you can use either. The unstructured version has less clutter in code but cannot be statically checked. You need to run the code to see at runtime if it throws the exception or it runs smoothly. Because of this, it actually is "uglier" from a C# perspective, where strong typing tries hard to leverage static dependencies so that compiletime checks are possible.
You can use dictionary instead.
IDictionary<int, string> dict = new Dictionary<int, string>()
{
{1,"One"},
{2, "Two"},
{3,"Three"}
};
Try the ValueTuples-Syntax:
public bool Insert(string table, params ValueTuple<string, string>[] keyValuePairs) { }
Then you can call the function like this:
db.Insert("personen",
( "firstname", "Test" ),
( "lastname", "Test 2" ),
( "address", "Teest" )
);

Returning integer and string

I have a function as follow. I need to return two parameters. First the index that is as list and it is done by the function. The other parameter that I need to return is a string str.
What would be your best suggestion for these outputs? a list with two different parameters? or what? Please let me know your ideas! Thanks
public List<int> index_selexted(TreeNodeCollection treeView, List<int> list)
{
List<int, List<string>> output_typ = new List<int, >();
foreach (TreeNode node in treeView)
{
if (node.Checked)
{
list.Add(node.Index);
string str = Regex.Match(node.Text, #" \((.*?)\) ").Groups[1].Value;
}
else
{
index_selexted(node.Nodes, list);
}
}
return list;
}
Well, since TreeNode.Index is not unique within the entire TreeNodeCollection then Dictionary<int, String> is not a choice, but Dictionary<int, List<String>> will do
//TODO: find a better name for dict
public Dictionary<int, List<String>> index_selexted(
TreeNodeCollection treeView,
Dictionary<int, List<String>> dict == null) { // == null for autocreation
if (null == treeView)
throw new ArgumentNullException("treeView");
if (null == dict)
dict = new Dictionary<int, List<String>>();
foreach (TreeNode node in treeView)
if (node.Checked) {
String match = Regex.Match(node.Text, #" \((.*?)\) ").Groups[1].Value;
List<String> list;
if (dict.TryGetValue(node.Index, out list))
list.Add(match);
else
dict.Add(node.Index, new List<String>() {match});
}
else
index_selexted(node.Nodes, dict);
return dict;
}
And so you'll have something like this as an output: index + all matches for it:
{1, ["abc", "def", "gh"]}
{3, ["xyz"]}
I've added dict == null in order to make the call easier:
// You don't have to pre-create the dictionary
var myDict = index_selexted(myTreeView.Nodes);
Use a Tuple
var res = new Tuple<string, List<string>>("string1", new List<string>());
You could either do
public class IndexSelectionResult{
public List<something> Index{get;set;}
public String StringResult
}
and return an instance of that, OR, if you're lazy, you can return a TUPLE:
public Tuple<List<string>, string>> myFunction(){ /* code */}
I believe you want this:
public static List<int> index_selexted(TreeNodeCollection treeView, out string str)
{
str = null;
var list = new List<int>();
var output_typ = new List<int>();
foreach (TreeNode node in treeView)
{
if (node.Checked)
{
list.Add(node.Index);
str = Regex.Match(node.Text, #" \((.*?)\) ").Groups[1].Value;
}
else
{
index_selexted(node.Nodes, list);
}
}
return list;
}
usage as such:
var treeview = sometreeview;
string output;
var result = index_selected(treeview, out output);
Console.WriteLine(output);
instead of using the list in your example (List> output_typ = new List();) consider
using a dictionary:
var output_typ = new Dictionary<int, List<string>>();
or a list of tuples:
var output_typ = new List<Tuple<int, List<string>>();
Hope this helps
There are a lot of ways to do this in fact, it depends on your specific use case which one you'd prefer.
Using a class
class MyResult {
public List<int> MyList { get; set; }
public string MyString { get; set; }
}
public MyResult index_selected(arg1..., arg2...) {
return new MyResult {
MyList = outputList,
MyString = "outputString"
}
}
Using a class is my preferred way. Though it may clutter if you have many return types it is by far the most readable solution.
Using a tuple
public Tuple<List<int>, string> index_selected(arg1..., arg2...) {
return Tuple.Create(outputList, "outputString");
}
My second goto option is a tuple. It is a lot more difficult to determine what the values contained in the tuple represent. But doesn't require creating more classes and is a quick solution (I use it mostly for private methods where readability is not much of a concern).
Using the out keyword
public List<int> index_selected(arg1..., out string resultString) {
resultString = null;
/* Doing calculations and such */
resultString = "
return outputList;
}
In this case the string passed to the resultString parameter will be replaced by whatever you assign to it in the method (see out keyword). Depending on your use case you may also want to look at the ref keyword.
This approach is rather error prone and is generally not preffered.

How to name dictionary/list with variable

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);
}
}

Counting values matched in an array

Ok so, I am looking through a document for certain values, and if they match the values in this array, then I want to increase the count for that specific value. I did this:
public static class Hex
{
//example only, not real code
public static string[] name = {"aba", "bcd", "c"};
public static int[] count = new int[name.Length];
}
But it seems like there must be a better/easier way. Maybe an array of tuple? I just don't know. I know its a pretty easy question, I just can't think of quite how to do it with both strings to compare in 1, and int count for them. Thanks!
use Dictionary<TKey, TValue> Class
Dictionary<string, int> dictionary = new Dictionary<string, int>();
dictionary.Add("aba", 0);
dictionary.Add("bcd", 0);
dictionary.Add("c", 0);
Later you can search for the word in Dictionary.Keys and increment the counter.
What about a Dictionary<string, int>?
I would use a Dictionary<string, int> since it is very efficient:
public static class Hex
{
static Hex()
{
_HexNameCounts = new Dictionary<string, int>()
{
{"aba", 0}, {"bcd", 0}, {"c", 0}
};
}
private static Dictionary<string, int> _HexNameCounts = null;
public static int? GetHexNameCount(string name)
{
int count;
if (_HexNameCounts.TryGetValue(name, out count))
return count;
return null;
}
public static void SetHexNameCount(string name, int count)
{
_HexNameCounts[name] = count;
}
public static void IncreaseHexNameCount(string name, int count = 1)
{
int c = GetHexNameCount(name) ?? 0;
SetHexNameCount(name, c + count);
}
}
Now you can use it in this way:
int? abaCount = Hex.GetHexNameCount("aba");
// or
Hex.SetHexNameCount("c", 3);
// or
Hex.IncreaseHexNameCount("foo", 10);
It's always good to encapsulate complexity in methods. That makes the code more readable and safer.
I have used a Nullable<int> to handle the case that the name is new.
Use a Dictionary:
Dictionary<string, int> matches = new Dictionary<string, int>();
foreach(var item in document)
{
if(matches.ContainsKey(item.stringvalue))
{
matches[item.stringvalue] += 1;
}
else
{
matches.Add(item.stringvalue, 1);
}
}
You can use a dictionary as bellow:
Dictionary<string, int> dicObj = new Dictionary<string, int>();
dicObj.Add("abc", 0);
…
After that you can search for the particular word in this using dicObj.ContainsKey and you can perform your business logic.

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