如何循环多个字典获取KVP?

How to loop through multiple dictionaries to obtain KVP?

我目前有 20 个 Dictionary 正在存储 TimeStamp Key 和 Vector3 Value。

例如

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

退出时,我试图遍历每个字典以生成带有时间戳和 X、Y、Z 坐标的 CSV。

我成功地手动生成了一到两个 CSV。

例如

foreach (KeyValuePair<string, Vector3> kvp in rWrist)
{
  writer.WriteLine("{0},{1},{2},{3}", kvp.Key, kvp.Value.x, kvp.Value.y, kvp.Value.z);
}

但是...手动为所有 20 部词典执行此操作会很痛苦。我完全不知道如何一次遍历每个字典。

例如

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

        }
    }

我不是软件开发人员,所以非常感谢任何帮助!

为清楚起见编辑: 我正在使用 HoloLens2 每隔 tick

轮询位置数据

使用内部时钟 - 每个刻度都存储为一个键,值被分配给该关节在该刻度处的 Vector3 位置

如果 HoloLens2 未检测到滴答作响的手指姿势,每个字典可能会或可能不会具有相同的时间戳。

我需要为每个关节导出不同的 .CSV 文件以进行数据分析

是否可以不考虑同时遍历所有字典,而实际上需要保留所有键的主列表,并遍历所有可能的字典键?在您的实例中,哪些是时间戳?这将允许您同时对每个字典进行操作。这是我在 LinqPad 中做的一个例子。 Dump() 类似于 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

您可以创建一个 IEnumerable<Dictionary<string, Vector3>>(有很多方法可以做到这一点)然后使用 SelectMany 将 key-value 对展平为一个维度:

var dictionaries = new[]
{
    rWrist,
    rThumbProximal,
    ...
}

foreach( var kvp in dictionaries.SelectMany(d => d) )
{
    ...
}

或者,只需将 Enumberable.Concat 个调用链接在一起

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

这样,您可以通过字符串作为键访问字典(在这种情况下可能是每个 body 部分的名称),或者简单地遍历它们以对每个部分执行相同的过程。

对于您提到的情况,我的猜测是您在遍历字典时可能不会更改值。但是,如果您需要这样做,在迭代字典时更改字典的值是不可行的。 You can check here for workarounds.

I need to export different .CSV for each joint for Data Analysis

据我了解,该要求与您之前的陈述相矛盾:

I am pretty lost on how I could iterate through each dictionary at once.

,但如果您需要将联合数据导出到单独的 .CSV 文件,我建议类似于以下内容:

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) 将简单地生成字符串 "rWrist",如果愿意,可以直接用字符串替换(例如 ["Right wrist"] = rWrist 而不是 [nameof(rWrist)] = rWrist)。)