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
CodePudding user response:
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
CodePudding user response:
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 ...;
CodePudding user response:
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.
CodePudding user response:
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).)
