How to loop through multiple dictionaries to obtain KVP? - c#

I currently have 20 Dictionary<string, Vector3> that are storing TimeStamp Key and Vector3 Value.
E.g.
Dictionary<string, Vector3> rWrist = new Dictionary<string, Vector3>();
Dictionary<string, Vector3> rThumbProximal = new Dictionary<string, Vector3>();
Dictionary<string, Vector3> rThumbDistal = new Dictionary<string, Vector3>();
Dictionary<string, Vector3> rThumbTip = new Dictionary<string, Vector3>();
Dictionary<string, Vector3> rIndexKnuckle = new Dictionary<string, Vector3>();
On exit, I am attempting to loop through each dictionary to generate a CSV with TimeStamp and X,Y,Z coordinates.
I was successful in generating a one to two CSVs manually.
E.g.
foreach (KeyValuePair<string, Vector3> kvp in rWrist)
{
writer.WriteLine("{0},{1},{2},{3}", kvp.Key, kvp.Value.x, kvp.Value.y, kvp.Value.z);
}
But... to do this manually for all 20 dictionaries would be a pain. I am pretty lost on how I could iterate through each dictionary at once.
E.g.
for (int i = 0; i < paths.Count; i++)
{
if (!File.Exists(paths[i]))
{
File.WriteAllText(paths[i], null);
}
using (var writer = new StreamWriter(paths[i]))
{
writer.WriteLine("{0},{1},{2},{3}", "Time", "xPos", "yPos", "zPos");
foreach (KeyValuePair<string, Vector3> kvp in LOOP-THROUGH-MULTIPLE-DICTIONARIES-HERE)
{
writer.WriteLine("{0},{1},{2},{3}", kvp.Key, kvp.Value.x, kvp.Value.y, kvp.Value.z);
}
}
}
I'm not a software developer by trade so any help would be greatly appreciated!
Edit for Clarity:
I am using HoloLens2 to poll positional data every tick
Using the internal clock - each tick is stored as a Key and the value is assigned the Vector3 position of that joint at that tick
Each dictionary may or may not have the same TimeStamps if HoloLens2 doesn't detect a finger pose that tick.
I need to export different .CSV for each joint for Data Analysis

I need to export different .CSV for each joint for Data Analysis
From my understanding, that requirement contradicts your previous statement:
I am pretty lost on how I could iterate through each dictionary at once.
, but if you need to export the joint data to separate .CSV files, I would suggest something similar to the following:
var vectorDataByJointName = new Dictionary<string, Dictionary<string, Vector3>>
{
[nameof(rWrist)] = rWrist,
[nameof(rThumbProximal)] = rThumbProximal,
[nameof(rThumbDistal)] = rThumbDistal,
[nameof(rThumbTip)] = rThumbTip,
[nameof(rIndexKnuckle)] = rIndexKnuckle,
// and so on for the remaining joints
};
foreach (var jointVectorData in vectorDataByJointName)
{
// File creation here (using jointVectorData.Key as file name?)
writer.WriteLine("{0},{1},{2},{3}", "Time", "xPos", "yPos", "zPos");
foreach (var kvp in jointVectorData.Value)
{
writer.WriteLine("{0},{1},{2},{3}", kvp.Key, kvp.Value.x, kvp.Value.y, kvp.Value.z);
}
}
(nameof(rWrist) will simply produce the string "rWrist", and may be replaced by strings directly if that's preferred (e.g. ["Right wrist"] = rWrist rather than [nameof(rWrist)] = rWrist).)

Is it possible instead of thinking about looping through all dictionaries at the same time you actually need to keep a master list of all your keys, and loop through all possible dictionary keys? Which in your instance are timestamps? This will then allow you to operate on each dictionary at the same time. Here is an example I did in LinqPad. The Dump() is similar to WriteLine().
var timestampKeys = new [] {"timestamp1","timestamp2","timestamp3"};
Dictionary<string, string> rWrist = new Dictionary<string, string>();
Dictionary<string, string> rThumbProximal = new Dictionary<string, string>();
rWrist.Add("timestamp1","vectorWrist1");
rWrist.Add("timestamp3","vectorWrist2");
rThumbProximal.Add("timestamp1","vectorThumb1");
rThumbProximal.Add("timestamp2","vectorThumb2");
rThumbProximal.Add("timestamp3","vectorThumb3");
foreach(var timestampKey in timestampKeys)
{
if(rWrist.ContainsKey(timestampKey))
rWrist[timestampKey].Dump();
if(rThumbProximal.ContainsKey(timestampKey))
rThumbProximal[timestampKey].Dump();
}
// outputs:
//vectorWrist1
//vectorThumb1
//vectorThumb2
//vectorWrist2
//vectorThumb3

You could create an IEnumerable<Dictionary<string, Vector3>> (many ways to go about doing that) then use SelectMany to flatten the key-value pairs into a single dimension:
var dictionaries = new[]
{
rWrist,
rThumbProximal,
...
}
foreach( var kvp in dictionaries.SelectMany(d => d) )
{
...
}
Alternatively, just chain Enumberable.Concat calls together
var kvPairs = rWrist.Concat( rThumbProximal )
.Concat( rThumbDistal )
... etc ...;

using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
// key = body part
// value = that body part's dictionary
Dictionary<string, Dictionary<string, string>> bigDic = new Dictionary<string, Dictionary<string, string>>();
// <string, string> instead of <string, Vector3>, for demonstration. You can use Vector3 as value without worries.
bigDic.Add("smallDic", new Dictionary<string, string>());
bigDic["smallDic"].Add("12345", "Old Position");
// write
foreach (Dictionary<string, string> sd in bigDic.Values)
{
sd.Add("12346", "New Position");
}
// read
foreach (Dictionary<string, string> sd in bigDic.Values)
{
foreach (string timestamp in sd.Keys)
{
Console.WriteLine(timestamp + ": " + sd[timestamp]);
}
}
}
}
This way, you can access the dictionary through string as keys (Maybe each body part's name, in this case), or simply iterate through them to do same process on each one.
With the case you're mentioning, my guess is you probably won't change the values when iterating through the dictionaries. However if you need to do so, change a dictionary's value while iterating through it is not viable. You can check here for workarounds.

Related

How do I iterate over a hashset of dictionaries

Apologies in advance; I am on day 3 of trying to learn C#.
I am instructed to build a hashset of dictionaries; no problem. I see that that has been built. I now need to iterate over the hashset and copy the entries to a new list if the dictionary's key != a particular string. Could someone kindly explain the proper syntax for achieving this seemingly simple task?
var goodSongs = new List<Dictionary<string,string>>();
var allSongs = new HashSet<Dictionary<string, string>>();
Dictionary<string, string> meatloaf = new Dictionary<string, string>();
meatloaf.Add("Meatloaf", "Paradise By The Dashboard Light");
Dictionary<string, string> aerosmith = new Dictionary<string,string>();
aerosmith.Add("Aerosmith", "Cryin'");
Dictionary<string, string> nickelback = new Dictionary<string, string>();
nickelback.Add("Nickelback", "Rockstar");
allSongs.Add(nickelback);
allSongs.Add(aerosmith);
allSongs.Add(meatloaf);
//foreach loop to iterate dictionaries goes here
Goal - To get unstuck, hope to learn C#, and decide if I want to keep going down this rabbit hole. Thanks to all.
Here is an example of how to iterate through the hashset and then the dictionary:
var all = new HashSet<Dictionary<string, string>>();
Dictionary<string, string> newDict = new Dictionary<string, string>();
newDict.Add("M", "T");
all.Add(newDict);
foreach(Dictionary<string,string> dict in all)
{
foreach(KeyValuePair<string,string> pair in dict)
{
string key = pair.Key;
string value = pair.Value;
}
}

single key but multiple value different row

I have
Dictionary idDictionary = new Dictionary();
within this Dictionary, I want, add two row with same key but values different
I used this Dictionary in many methods that a global Dictionary in one method has that issue. if I changed like all u suggest another method get error
Try something like this.
Dictionary<string, List<string>> obj = new Dictionary<string, List<string>>();
List<string> keyValue = new List<string>();
keyValue.Add("a");
keyValue.Add("b");
obj.Add("key1", keyValue);
foreach (KeyValuePair<string, List<string>> entry in obj)
{
// do something with entry.Value or entry.Key
}
List<string> keyValueOutput = new List<string>();
if (obj.TryGetValue("key1",out keyValueOutput))
{
foreach (string s in keyValueOutput)
{
// do something with entry.Value or entry.Key
}
}

Dictionary if Key exist append if not add new element C#

I am having
Dictionary<String, List<String>> filters = new Dictionary<String, List<String>>();
which is having values like country = us. till now I am able to add it when key is not repeated. now when key country is repeated. it is showing that the key is already present.
what I want is How to add multiple values in the same key. I am not able to do it. Please suggest something.
for (int i = 0; i < msgProperty.Value.Count; i++)
{
FilterValue.Add(msgProperty.Value[i].filterValue.Value);
filterColumn = msgProperty.Value[i].filterColumnName.Value;
filters.Add(filterColumn, FilterValue);
}
what I want
country = US,UK
The different types of all your variables are a bit confusing, which won't help you writing the code. I'm assuming you have a Dictionary<string, List<string>> where the key is a "language" and the value is a list of countries for that language, or whatever. Reducing a problem to a minimal set that reproduces the issue is very helpful when asking for help.
Anyway assuming the above, it's as simple as this:
Try to get the dictionary["somelanguage"] key into existingValue.
If it doesn't exist, add it and store it in the same variable.
Add the List<string> to the dictionary under the "somelanguage" key.
The code will look like this:
private Dictionary<string, List<string>> dictionary;
void AddCountries(string languageKey, List<string> coutriesToAdd)
{
List<string> existingValue = null;
if (!dictionary.TryGetValue(languageKey, out existingValue))
{
// Create if not exists in dictionary
existingValue = dictionary[languageKey] = new List<string>()
}
existingValue.AddRange(coutriesToAdd);
}
You simply need to check whether the value exists in the dictionary, like this:
if (!filters.ContainsKey("country"))
filters["country"] = new List<string>();
filters["country"].AddRange("your value");
Assuming you are trying to add value for key country
List<string> existingValues;
if (filters.TryGetValue(country, out existingValues))
existingValues.Add(value);
else
filters.Add(country, new List<string> { value })
If your values is List<string>
List<string> existingValues;
if (filters.TryGetValue(country, out existingValues))
existingValues.AddRange(values);
else
filters.Add(country, new List<string> { values })
Make use of IDictionary interface.
IDictionary dict = new Dictionary<String, List<String>>();
if (!dict.ContainsKey("key"))
dict["key"] = new List<string>();
filters["key"].Add("value");

Adding new element within a list inside a dictionary

In a dictionary, I want to add a list of numbers for a given key.But I am unable to do it.
for(int i = 0 ; i < size ; i++){
string input = Console.ReadLine();
string[] inputList = input.Split(' ');
count[Convert.ToInt32(inputList[0])]++;
if(!map.ContainsKey(Convert.ToInt32(inputList[0]))){
map.Add(Convert.ToInt32(inputList[0]),new List<string>());
map_index.Add(Convert.ToInt32(inputList[0]),new List<int>());
}
}
The question is bit unclear. My understanding of your problem is as follows: You have a dictionary, a value of the dictionary is a list, and you have trouble adding an item to that list. Since you didn't explain your notation I'm using more general names, just to give you an idea what has to be done:
Dictionary<int, List<string>> myDict = new Dictionary<int, List<string>>();
if (myDict.ContainsKey(myKey))
{
myDict[myKey].Add(myVal);
}
else
{
myDict[myKey] = new List<string> { myVal };
}
If the key is not in the dictionary you create an entry together with the list and initialize the list with the new value. If the key is there you just access the list (by using myDict[myKey]) and add the new value to the list. Since the list is always created for a new key you don't have to worry that it's not initialized when adding a value for an existing key.
This could be one the efficient Solution and much easier than if-else.
Dictionary<int, List<string>> myDict = new Dictionary<int, List<string>>();
try
{
myDict[myKey].Add(myVal);
}
catch
{
myDict[myKey] = new List<string> { myVal };
}
There is a 'one-command-line' way to do this using AddOrUpdate from ConcurrentDictionary:
using System.Linq;
using System.Collections.Generic;
using System.Collections.Concurrent;
...
var dictionary = new ConcurrentDictionary<int, string[]>();
var itemToAdd = "item to add to key-list";
dictionary.AddOrUpdate(1, new[]{item1ToAdd}, (key, list) => list.Append(itemToAdd));
// If key 1 doesn't exist, creates it with a list containing itemToAdd as value
// If key 1 exists, adds item to already existent list (third parameter)

Making a List<string> from Dictionary<string, string>

I was wondering if it were possible to make a list from the dictionary values where the key is a specified value?
The dictionary would like this:
Sidcup - DPC1
Sidcup - DPC2
Blackheath - DPC3
Blackheath - DPC4
Bexleyheath - DPC5
In fact, I'm not entirely implementing a Dictionary as above is a good idea. Here is its implementation:
DataSet ds = EngineBllUtility.GetDPCsForImportFile(connectionString, fileID);
if (ds.Tables.Count > 0)
{
DataTable dtDPCs = EngineBllUtility.GetDPCsForImportFile(connectionString, fileID).Tables[0];
Dictionary<string, string> preliminaryList = new Dictionary<string, string>();
if (dtDPCs.Columns.Contains("DPCNumber") && dtDPCs.Columns.Contains("BranchName"))
foreach (DataRow dataRow in dtDPCs.Rows)
{
preliminaryList.Add(dataRow["BranchName"].ToString(), dataRow["DPCNumber"].ToString());
}
I have the following code: (Excuse the last line, its just so you have an idea of what I'm trying to do).
foreach (string branch in branchNames)
{
string subfolder = System.IO.Path.Combine(saveLocation, branch);
System.IO.Directory.CreateDirectory(subfolder);
List<string> certificateList = new List<string>();
certificateList.Add(DPCNumber in preliminaryList where Key = branch);
}
In the above the branch is the key from the Dictionary. I need to iterate through because it needs to create a new folder and then do something with the certificateList I am creating.
Sure:
private static void TestZip()
{
Dictionary<string, string> stringstringdic = new Dictionary<string, string>();
stringstringdic.Add("1", "One");
stringstringdic.Add("2", "Two");
stringstringdic.Add("3", "Three");
stringstringdic.Add("4", "Four");
stringstringdic = stringstringdic.Where(pair => pair.Key != "1")
.ToDictionary(pair => pair.Key, pair => pair.Value);
List<string> stringlist = stringstringdic.Keys.Concat(stringstringdic.Values).ToList();
foreach (string str in stringlist)
{
Console.WriteLine(str);
}
}
//Output:
//2
//3
//4
//Two
//Three
//Four
Of course, you'll have to change the Where clause to reflect your real need.
If I understood you right, it's like .Where(pair => pair.Key == branch)
If I understand you correctly you want to add the value based on a key to a separate List?
certificateList.Add(preliminaryList[branch])
This is simplified as I really need to see the declaration of preliminaryList to know how DPCNumber fits into all of it. Could it be...
certificateList.Add(preliminaryList[branch].ToString())
To simply create a list of keys you can do the following.
var dictionary = new Dictionary<string, string>();
dictionary.Add("key1", "value1");
dictionary.Add("key2", "value2");
dictionary.Add("key3", "value3");
dictionary.Add("key4", "value4");
dictionary.Add("key5", "value5");
var list = dictionary.Keys.ToList();
This should give you a list with values "key1", "key2", "key3", "key4", "key5".
You can put a where clause in to filter out certain keys. The following gives all keys which contain a "2" (random example), resulting in just "key2".
var filteredList = dictionary.Keys.Where(key => key.Contains("2")).ToList();
Edit:
To get a value given a specific key.
string value = dictionary["key1"];
Note, the key is a dictionary must be unique, so for a given key you will only ever get a single value back and not a list of values.

Categories