如何循环多个字典获取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
)。)
我目前有 20 个 Dictionary
例如
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
)。)