0

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

NeuroLabs
  • 7
  • 2

4 Answers4

0

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
patawa91
  • 46
  • 2
  • not sure what's the actual data flow, but if you can decide what containers to put data, I'd suggest maybe a Dictionary>(); ? In this case, each dictionary won't have different variable names assigned. Instead, the top Dictionary has each body part's name as key, this way they can be accessed either by hard-code or iteration easily. If you're thinking about "Doing this x times is tiresome" - then that might be a hint telling you there's a programatic way to do what you want to achieve. – Xiang Wei Huang Jan 26 '22 at 05:43
0

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 ...;
Moho
  • 15,457
  • 1
  • 30
  • 31
0
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.

Xiang Wei Huang
  • 336
  • 1
  • 9
0

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).)

Astrid E.
  • 2,280
  • 2
  • 6
  • 17
  • @NeuroLabs Would you mind explaining why you unaccepted this answer? It may help others in the future to see why this wasn't what you needed, even though you thought it was to begin with. – Astrid E. Feb 01 '22 at 07:59
  • My apologies, I mistakenly unaccepted this answer and did not realize. Your response was very helpful and helped generate the outcome I was looking for. Thank you once again for all your help – NeuroLabs Feb 04 '22 at 05:44
  • Oh, okay. Great, I'm happy I could be of help! – Astrid E. Feb 04 '22 at 06:17