C# 作为字典中的键访问双数组的最快方法
我有一个C# 作为字典中的键访问双数组的最快方法,c#,c#-4.0,C#,C# 4.0,我有一个double[]数组,我想将它用作键(不是字面意义上的,而是在需要匹配double数组中的所有double时匹配键的方式) 使用double[]数组作为字典键的最快方法是什么 它在使用吗 字典(将double[]转换为字符串) 或 假设转换所有的密钥数组都具有相同的长度,或者考虑使用元组< /代码>,或者使用数组上的结构相等比较器。 对于元组: var yourDidt = new Dictionary<Tuple<double, double, double>, st
double[]
数组,我想将它用作键(不是字面意义上的,而是在需要匹配double数组中的所有double时匹配键的方式)
使用double[]
数组作为字典键的最快方法是什么
它在使用吗
字典
(将double[]转换为字符串)
或
假设转换所有的密钥数组都具有相同的长度,或者考虑使用<代码>元组< /代码>,或者使用数组上的结构相等比较器。
对于元组:
var yourDidt = new Dictionary<Tuple<double, double, double>, string>();
yourDict.Add(Tuple.Create(3.14, 2.718, double.NaN), "da value");
string read = yourDict[Tuple.Create(3.14, 2.718, double.NaN)];
还考虑Sergey Berezovskiy提出的创建自定义类或(不可变的)的建议。Stutt来保存你的代码集>双< /代码> .S.这样你就可以用一种自然的方式命名你的类型和它的成员,使你更清楚你所做的事情。如果需要的话,你的类/结构可以很容易地被扩展。
假设所有的密钥数组都有相同的长度,或者考虑使用<代码>元组< /代码>,或者使用一个结构等式。数组上的比较器 对于元组:var yourDidt = new Dictionary<Tuple<double, double, double>, string>();
yourDict.Add(Tuple.Create(3.14, 2.718, double.NaN), "da value");
string read = yourDict[Tuple.Create(3.14, 2.718, double.NaN)];
还考虑Sergey Berezovskiy提出的创建自定义类或(不可变的)的建议。结构来保存你的
double
s集合。这样你可以用一种自然的方式来命名你的类型和它的成员,使你的操作更加清晰。如果需要的话,你的类/结构以后可以很容易地扩展。因此所有数组都有相同的长度,数组中的每一项都有特定的含义,然后创建一个类来保存所有的项具有描述性名称的属性。例如,您可以使用带有属性X
和Y
的类点
,而不是带有两个项的双数组。然后重写该类的等于和GetHashCode
,并将其用作键(请参阅):
因此,所有数组都具有相同的长度,数组中的每个项都有特定的含义,然后创建一个类,该类将所有项作为具有描述性名称的属性保存。例如,您可以使用具有属性的classPoint
和Y
。然后覆盖Equals
和GetHashCode>代码>并将其用作键(请参阅):
[P>]不认为这是一个单独的答案;这是@ JpppStnnelels'的回答[/P>的延伸]。
我只想指出,您将Jeppe的方法概括如下:
public class StructuralEqualityComparer<T>: IEqualityComparer<T>
{
public bool Equals(T x, T y)
{
return StructuralComparisons.StructuralEqualityComparer.Equals(x, y);
}
public int GetHashCode(T obj)
{
return StructuralComparisons.StructuralEqualityComparer.GetHashCode(obj);
}
public static StructuralEqualityComparer<T> Default
{
get
{
StructuralEqualityComparer<T> comparer = _defaultComparer;
if (comparer == null)
{
comparer = new StructuralEqualityComparer<T>();
_defaultComparer = comparer;
}
return comparer;
}
}
private static StructuralEqualityComparer<T> _defaultComparer;
}
[P>]不认为这是一个单独的答案;这是@ JpppStnnelels'的回答[/P>的延伸]。
我只想指出,您将Jeppe的方法概括如下:
public class StructuralEqualityComparer<T>: IEqualityComparer<T>
{
public bool Equals(T x, T y)
{
return StructuralComparisons.StructuralEqualityComparer.Equals(x, y);
}
public int GetHashCode(T obj)
{
return StructuralComparisons.StructuralEqualityComparer.GetHashCode(obj);
}
public static StructuralEqualityComparer<T> Default
{
get
{
StructuralEqualityComparer<T> comparer = _defaultComparer;
if (comparer == null)
{
comparer = new StructuralEqualityComparer<T>();
_defaultComparer = comparer;
}
return comparer;
}
}
private static StructuralEqualityComparer<T> _defaultComparer;
}
好的,这是我到目前为止发现的:
我在字典中输入一个条目(长度为4 arrray),并在我的机器上访问它999999次:
字典(
新的DoubleArrayStructuralQualityComparer());
需要1.75秒
字典
需要0.85秒
下面的代码需要0.1755285秒
,这是现在最快的速度!(与Sergey的评论一致)
最快的-Matthew Watson的DoubleArrayComparer
代码需要0.15秒
public class DoubleArray
{
private double[] d = null;
public DoubleArray(double[] d)
{
this.d = d;
}
public override bool Equals(object obj)
{
if (!(obj is DoubleArray)) return false;
DoubleArray dobj = (DoubleArray)obj;
if (dobj.d.Length != d.Length) return false;
for (int i = 0; i < d.Length; i++)
{
if (dobj.d[i] != d[i]) return false;
}
return true;
}
public override int GetHashCode()
{
unchecked // Overflow is fine, just wrap
{
int hash = 17;
for (int i = 0; i < d.Length;i++ )
{
hash = hash*23 + d[i].GetHashCode();
}
return hash;
}
}
}
公共类双数组
{
private double[]d=null;
公共双数组(双[]d)
{
这个。d=d;
}
公共覆盖布尔等于(对象对象对象)
{
如果(!(obj为DoubleArray))返回false;
双数组dobj=(双数组)obj;
如果(dobj.d.Length!=d.Length)返回false;
对于(int i=0;i
好的,这是我目前发现的:
我在字典中输入一个条目(长度为4 arrray),并在我的机器上访问它999999次:
字典(
新的DoubleArrayStructuralQualityComparer());
需要1.75秒
字典
需要0.85秒
下面的代码需要0.1755285秒
,这是现在最快的速度!(与Sergey的评论一致)
最快的-Matthew Watson的DoubleArrayComparer
代码需要0.15秒
public class DoubleArray
{
private double[] d = null;
public DoubleArray(double[] d)
{
this.d = d;
}
public override bool Equals(object obj)
{
if (!(obj is DoubleArray)) return false;
DoubleArray dobj = (DoubleArray)obj;
if (dobj.d.Length != d.Length) return false;
for (int i = 0; i < d.Length; i++)
{
if (dobj.d[i] != d[i]) return false;
}
return true;
}
public override int GetHashCode()
{
unchecked // Overflow is fine, just wrap
{
int hash = 17;
for (int i = 0; i < d.Length;i++ )
{
hash = hash*23 + d[i].GetHashCode();
}
return hash;
}
}
}
公共类双数组
{
private double[]d=null;
公共双数组(双[]d)
{
这个。d=d;
}
公共覆盖布尔等于(对象对象对象)
{
如果(!(obj为DoubleArray))返回false;
双数组dobj=(双数组)obj;
如果(dobj.d.Length!=d.Length)返回false;
对于(int i=0;i
Yo知道两个具有相同值的数组将给出不同的键(因为它们不相等)?为什么要将数组用作键,而不将其自身加倍?@SergeyBerezovskiy我已经改变了问题Dictionary有什么问题?@NWard基本上我需要的是数组中的所有加倍都要匹配。你知道两个数组具有相同的
class DoubleArrayComparer: IEqualityComparer<double[]>
{
public bool Equals(double[] x, double[] y)
{
if (x == y)
return true;
if (x == null || y == null)
return false;
if (x.Length != y.Length)
return false;
for (int i = 0; i < x.Length; ++i)
if (x[i] != y[i])
return false;
return true;
}
public int GetHashCode(double[] data)
{
if (data == null)
return 0;
int result = 17;
foreach (var value in data)
result += result*23 + value.GetHashCode();
return result;
}
}
...
var yourDict = new Dictionary<double[], string>(new DoubleArrayComparer());
public class DoubleArray
{
private double[] d = null;
public DoubleArray(double[] d)
{
this.d = d;
}
public override bool Equals(object obj)
{
if (!(obj is DoubleArray)) return false;
DoubleArray dobj = (DoubleArray)obj;
if (dobj.d.Length != d.Length) return false;
for (int i = 0; i < d.Length; i++)
{
if (dobj.d[i] != d[i]) return false;
}
return true;
}
public override int GetHashCode()
{
unchecked // Overflow is fine, just wrap
{
int hash = 17;
for (int i = 0; i < d.Length;i++ )
{
hash = hash*23 + d[i].GetHashCode();
}
return hash;
}
}
}