Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 对于多个属性(键)和作为值的列表,最合适的数据类型是什么?_C#_.net_Linq_Types_Windows Phone - Fatal编程技术网

C# 对于多个属性(键)和作为值的列表,最合适的数据类型是什么?

C# 对于多个属性(键)和作为值的列表,最合适的数据类型是什么?,c#,.net,linq,types,windows-phone,C#,.net,Linq,Types,Windows Phone,我需要某种“复杂”的数据类型来存储我的数据: 3个属性:角度、宽度、高度 一个包含多达4000个项目的大列表,我希望将其归类为组,每个属性的值都较高/较低/相等 我需要一个数据类型来将这三个属性的每个组合存储为适合这三个类别的项的(子)列表 编辑:还有一种特殊情况,即属性高度可以有所有值(例如100-200、200-300、300-400;但也可以是100-400) 此数据类型应非常快速,在指定三个属性的值时,支持获取项目(子)列表的可能性 我想象如下: dataType[angle][wi

我需要某种“复杂”的数据类型来存储我的数据:

  • 3个属性:角度、宽度、高度
  • 一个包含多达4000个项目的大列表,我希望将其归类为组,每个属性的值都较高/较低/相等
  • 我需要一个数据类型来将这三个属性的每个组合存储为适合这三个类别的项的(子)列表
  • 编辑:还有一种特殊情况,即属性高度可以有所有值(例如100-200、200-300、300-400;但也可以是100-400)
  • 此数据类型应非常快速,在指定三个属性的值时,支持获取项目(子)列表的可能性
我想象如下:

dataType[angle][width][height]-->返回一个列表,其中的项目完全适合这三个类别

它类似于一个键值对,但有三个键,值是(子)列表

我现在不确定C#(适用于WindowsPhone)中实现的最佳(和性能最高)数据类型是: -我可以通过ObservableCollection和Linq查询轻松地完成这项工作。但这将是缓慢的,也许是矫枉过正 -我认为内部数据库可能也有点过分,尤其是我认为WindowsPhone上的数据库有点慢。。。 -我还遗漏了什么(字典、杂烩等)


非常感谢您的任何建议!(我希望,我能把我的问题描述得通俗易懂。)

你可以尝试在列表中使用Tuple


我们可以创建一个类来保存您拥有的三段数据,只要我们为该类型提供合理的
等于
GetHashCode
实现,我们就可以将其用作
字典
中的键,这是一种基于哈希的结构,具有非常快的查找速度

public class Foo : IEquatable<Foo> //TODO give better name
{
    public double Angle { get; set; }
    public double Width { get; set; }
    public double Height { get; set; }

    public override bool Equals(object obj)
    {
        return Equals(obj as Foo);
    }

    public bool Equals(Foo other)
    {
        if (other == null)
            return false;
        return Angle == other.Angle &&
            Width == other.Width &&
            Height == other.Height;
    }

    public override int GetHashCode()
    {
        return new { Angle, Width, Height }.GetHashCode();
    }
}
由此,我们可以编写一个方法来获取给定范围内的排序列表中的所有项:

public static IEnumerable<T> GetWithinRange<T>
    (this IList<T> collection, T start, T end,
    IComparer<T> comparer = null)
{
    comparer = comparer ?? Comparer<T>.Default;
    int index = collection.BinarySearch(start, comparer);
    while (index < collection.Count &&
        comparer.Compare(collection[index], end) <= 0)
    {
        yield return collection[index];
        index++;
    }
}
公共静态IEnumerable GetWithinRange
(此IList集合,T开始,T结束,
IComparer比较器=空)
{
比较器=比较器??比较器。默认值;
int index=collection.BinarySearch(start,comparer);
while(索引comparer.Compare(集合[索引],结束)使用元组作为键,列表作为值的词典?使用
列表
并不能提供非常高效的搜索速度;最终需要搜索集合中的每一项才能找到它。
元组
对于这样的结构来说也不是一个很好的主意;对于要搜索的类型的用户来说,这相当麻烦请记住哪一项对应于这三个值中的每一个。几乎可以肯定,具有有意义名称的自定义类型是值得努力的。您好,Servy。非常感谢您的建议,这对我来说非常好。不幸的是,我忘了提到一种特殊情况,即属性高度可以同时包含所有值(例如,100-200、200-300、300-400;但也有100-400)。您是否看到了一个仍然可以使用哈希代码的解决方案?(我很想使用哈希代码,因为它非常快)。谢谢!@casaout您可以这样做,但它让我的生活变得更加艰难。谢谢您的精彩和宝贵的帮助!我还可以坚持使用第一个版本和(对于高度的所有三个属性)只需获取这三个散列的值(因为这是固定的)并将其合并。您认为如何?@casaout如果它总是一个非常小的范围,那么当然,这是一个选项。
public static IEnumerable<T> GetWithinRange<T>
    (this IList<T> collection, T start, T end,
    IComparer<T> comparer = null)
{
    comparer = comparer ?? Comparer<T>.Default;
    int index = collection.BinarySearch(start, comparer);
    while (index < collection.Count &&
        comparer.Compare(collection[index], end) <= 0)
    {
        yield return collection[index];
        index++;
    }
}
public class Vector : IEquatable<Vector> //TODO consider renaming
{
    public double Angle { get; set; }
    public double Width { get; set; }

    public override bool Equals(object obj)
    {
        return Equals(obj as Vector);
    }

    public bool Equals(Vector other)
    {
        if (other == null)
            return false;
        return Angle == other.Angle &&
            Width == other.Width;
    }

    public override int GetHashCode()
    {
        return new { Angle, Width }.GetHashCode();
    }
}
Dictionary<Vector, SortedList<double, List<Something>>>
public class FooDataStructure //TODO rename
{
    private Dictionary<Vector, SortedList<double, List<Something>>> dictionary
        = new Dictionary<Vector, SortedList<double, List<Something>>>();

    public void Add(Foo foo, Something something)
    {
        var vector = new Vector { Angle = foo.Angle, Width = foo.Width };
        SortedList<double, List<Something>> list;
        if (!dictionary.TryGetValue(vector, out list))
        {
            list = new SortedList<double, List<Something>>();
            dictionary.Add(vector, list);
        }
        List<Something> somethings;
        if (!list.TryGetValue(foo.Height, out somethings))
        {
            somethings = new List<Something>();
            list.Add(foo.Height, somethings);
        }
        somethings.Add(something);
    }

    public IEnumerable<Something> Find(
        double angle, double width, double minHeight, double maxHeight)
    {
        var vector = new Vector { Angle = angle, Width = width };
        SortedList<double, List<Something>> list;
        if (!dictionary.TryGetValue(vector, out list))
        {
            return Enumerable.Empty<Something>();
        }
        return list.Keys.GetWithinRange(minHeight, maxHeight)
            .SelectMany(key => list[key]);
    }
}