【问题标题】:Creating a data structure with 1 key, 2 values in C# and also retrieving values for a particular key在 C# 中创建具有 1 个键、2 个值的数据结构,并检索特定键的值
【发布时间】:2017-12-12 15:34:27
【问题描述】:

我想创建一个有 1 个键,2 个值的数据结构,如下所示:

List<KeyValuePair<double, double, double>> list = new List<KeyValuePair<double, double, double>>();

我基本上有 x、y、z 坐标值,我想继续将它们附加到数据结构中。在附加数据之后,我想检索所有可用的“x”(类似于“列表”) .对于x的每个值,我想找到多个“y”值。然后对于特定的“x”和“y”值,我想找到所有的多个“z”值。

例如:如果我有像 (1,2,3) 这样的坐标; (1,3,4) ; (1,2,6); (1,2,9) 对于 1 的值,我想检索 2 和 3。同样,对于 1,2 的值;我想检索值 6 和 9。

如果有人可以让我知道在 C# 中执行此操作的过程,我将非常高兴。 提前致谢。

【问题讨论】:

  • 正如名称KeyValuePair 所说,它是存储一个键和一个值。在这里,您有 3 个值并且没有键,一个简单的元组就是您要查找的数据结构。这个不是。
  • 为什么不用Dictionary&lt;double, Tuple&lt;double, double&gt;&gt; 甚至Dictionary&lt;double, Dictionary&lt;double, List&lt;double&gt;&gt;&gt;
  • 你为什么要使用数据结构,为什么不创建一个保存数据的类(A DTO),你可以做任何你想做的事?
  • 这听起来像你需要一个 multiple key 字典。谷歌一下,有很多重复的。 @RaniDevpr,DTO 与算法标签有什么关系,这意味着检索性能和存储效率?你的意思是“使用数据库来存储它们并运行查询来检索你需要的东西”?
  • 使用适当的类来保存您的 X/Y/Z 值,这将使您的代码更具可读性。

标签: c# algorithm data-structures


【解决方案1】:

您没有唯一的键,并且您有不同宽度的键,因此字典或 KeyValuePair 会为您提供帮助。

如果在查找单个值((X, Y, Z) 的 X)时,您只对 Y 感兴趣而不对 Z 感兴趣,您可以用未使用的值填充键并将记录存储两次(因此键值-成对的 (1, 2, 3) 变为 (0, 1, 2)(1, 2, 3)),但这并不能真正让事情变得更清楚。

您可以将记录存储在List&lt;Tuple&lt;double, double, double&gt;&gt;

var list = new List<Tuple<double, double, double>>
{
    Tuple.Create<double, double, double>(1,2,3),
    Tuple.Create<double, double, double>(1,3,4),
    Tuple.Create<double, double, double>(1,2,6),
    Tuple.Create<double, double, double>(1,2,9),
};

var search = 1d;

var results = list.Where(t => t.Item1 == search)
                  .Select(t => t.Item2);

然后,当您要搜索两个值时,也可以使用元组:

var search = Tuple.Create<double, double>(1, 2);

var results = list.Where(t => t.Item1 == search.Item1 && t.Item2 == search.Item2)
                  .Select(t => t.Item3);

【讨论】:

  • @DragandDrop 这意味着为一个简单的 3 值类/结构导入整个库?矫枉过正,并可能滥用这种类型。
  • @DavidG,我认为 op 的名称表明真正的类可能很有用,因为它包括向量和方法。可能有点矫枉过正,我认为值得一提。
  • @DragandDrop 至少值得一提 4 次!你让我很开心 x)
【解决方案2】:

基本上是 CodeCaster 的答案,但有方法(我花时间创建它,但他更快:))

public void TestMethod()
{
    List<Tuple<double, double, double>> list = new List<Tuple<double, double, double>>();
    list.Add(new Tuple<double, double, double>(1, 2, 3));
    list.Add(new Tuple<double, double, double>(1, 2, 5));
    list.Add(new Tuple<double, double, double>(8, 2, 3));
    list.Add(new Tuple<double, double, double>(1, 5, 3));

    var x = GetIt(1, list);
    var y = GetIt(1, 2, list);
}

public List<double> GetIt(double d, List<Tuple<double, double, double>> list)
{
    return (from a in list
            where a.Item1 == d
            select a.Item2).Distinct().ToList();
}

public List<double> GetIt(double d, double e, List<Tuple<double, double, double>> list)
{
    return (from a in list
            where a.Item1 == d && a.Item2 == e
            select a.Item3).Distinct().ToList();
}

【讨论】:

  • OP 还希望在搜索单个值时返回单个值。
  • params double[] ?
  • @CodeCaster:他写道:“对于值 1,我想检索 2 和 3。”所以对我来说,结果是一个列表
  • 那是因为他们的测试数据包含那个。他们说:“对于 x 的每个值,我想找到多个“y”值 [来自 (x, y, z)]。”
  • 好的,发现另一个问题:重复!
【解决方案3】:

有多种方法可以满足您的需求。如果您使用的是 VS2017+,则可以使用 Value Tuple(针对 .NET4.7 时为原生,否则在 Nuget 中可用)

var list = new List<(double x, double y, double z)>();
list.Add((1,2,3));
list.Add((1,3,4));
list.Add((1,2,6));
list.Add((1,2,9));

并使用 Linq 按 x、y 和 z 分组。

用 x=1 检索所有 y

var l1 = list.Where(i=>i.x==1).Select(i=>i.y);

检索所有 x=1 和 y=2 的 z

var l2 = list.Where(i=>i.x==1 && i.y==2).Select(i=>i.z);

【讨论】:

    【解决方案4】:

    我不推荐使用 Dictionary 类型的方法,因为您要存储的是 3 个值,而不是键和值。

    我建议如下:

    1. 创建类坐标
    2. 列出该类的列表
    3. 使用 LINQ 完成它。

    例如:

     public class Coordinates
    {
        public float XCoord { get; set; }
        public float YCoor { get; set; }
        public float ZCoor { get; set; }
    }
    

    然后您可以创建一个列表并使用 LINQ 选择所需的数据,在此示例中,我创建了一个接受 X、Y 和 Z 的函数来过滤列表。

    List<Coordinates> list = new List<Coordinates>(); //Populate the list
    

    然后用下面的方法:

    public List<Coordinates> SelectCoords(List<Coordinates> originalList, float? X, float? Y,float? Z)
        {
            List<Coordinates> filteredList = new List<Coordinates>(originalList);
    
            if (X != null)
            {
                filteredList = filteredList.Where(v => v.XCoord == X).ToList();
            }
    
            if (Y != null)
            {
                filteredList = filteredList.Where(v => v.YCoord == Y).ToList();
            }
    
            if (X != null)
            {
                filteredList = filteredList.Where(v => v.ZCoord == Z).ToList();
            }
    
            return filteredList;
        }
    

    让您选择如何过滤列表,只返回带有 X、Y 和或 Z 的列表

    list = SelectCoords(list, 1, 2,null);
    

    【讨论】:

      【解决方案5】:

      Ms 支持您并为此开设课程以防万一:Point3D structure

      优点:它有许多可以完全使用的内置方法。你可以玩转点和矢量。

      缺点:如果您只是存储这 3 个双精度值,那就太过分了。

      【讨论】:

      • 存储这三个值的数据类型不是这个问题的有趣部分。反正不是我的反对票。
      • @CodeCaster,没有足够的时间将代码编辑为答案我想这是我的错。因为这个答案回答了问题的一部分。它会留下来。基本上代码现在将与每个人都带有相同的 linQ。在字段、属性上使用正确的名称。
      • 即使使用正确的数据结构不是问题的主要部分,它也是主要问题。解决它不仅仅是对我的评论。
      猜你喜欢
      • 2019-09-30
      • 2021-12-28
      • 2010-09-20
      • 1970-01-01
      • 2012-08-08
      • 1970-01-01
      • 2012-03-05
      • 1970-01-01
      • 2018-07-18
      相关资源
      最近更新 更多