礼貌的木瓜 · 科技创新 建筑美好未来-广东省住房和城乡建设厅· 1 月前 · |
率性的春卷 · 应对疫情防控常态化,多地P2实验室建设“快跑 ...· 7 月前 · |
迷茫的手术刀 · 澳洲女子无法生育,化身恶魔房东残杀单身母亲并 ...· 1 年前 · |
爱运动的小虾米 · 超自然觉醒漫画免费 - 超自然觉醒漫画 - ...· 1 年前 · |
追风的烤地瓜 · 古代那么多金子银子,后来都去哪里了?为什么如 ...· 1 年前 · |
我正在尝试用C#制作一个字典查询表。我需要将一个三元组的值解析为一个字符串。我尝试使用数组作为键,但这不起作用,我不知道还能做什么。在这一点上,我正在考虑制作一个字典的字典,但这可能看起来不是很漂亮,尽管这是我在javascript中如何做的。
我会用合适的GetHashCode覆盖您的元组,并将其用作键。
只要你重载了正确的方法,你就会看到不错的性能。
如果您使用的是.NET 4.0,请使用元组:
lookup = new Dictionary<Tuple<TypeA, TypeB, TypeC>, string>();
如果没有,您可以定义一个
Tuple
并将其用作键。元组需要重写
GetHashCode
、
Equals
和
IEquatable
struct Tuple<T, U, W> : IEquatable<Tuple<T,U,W>>
readonly T first;
readonly U second;
readonly W third;
public Tuple(T first, U second, W third)
this.first = first;
this.second = second;
this.third = third;
public T First { get { return first; } }
public U Second { get { return second; } }
public W Third { get { return third; } }
public override int GetHashCode()
return first.GetHashCode() ^ second.GetHashCode() ^ third.GetHashCode();
public override bool Equals(object obj)
if (obj == null || GetType() != obj.GetType())
return false;
return Equals((Tuple<T, U, W>)obj);
public bool Equals(Tuple<T, U, W> other)
return other.first.Equals(first) && other.second.Equals(second) && other.third.Equals(third);
}
如果出于某种原因,您确实希望避免创建自己的元组类或使用内置到.NET 4.0中的元组类,还有一种可能的方法;您可以将这三个键值组合到一个值中。
例如,如果这三个值是不超过64位的整数类型,则可以将它们组合到一个
ulong
中。
最坏的情况是,你总是可以使用一个字符串,只要你确保其中的三个部分用一些字符或序列分隔,而这些字符或序列不会出现在键的组件中,例如,你可以尝试使用三个数字:
string.Format("{0}#{1}#{2}", key1, key2, key3)
显然,在这种方法中有一些组合开销,但取决于您使用它来做什么,这可能足够微不足道,不需要关心它。
下面是供参考的.NET元组:
[Serializable]
public class Tuple<T1, T2, T3> : IStructuralEquatable, IStructuralComparable, IComparable, ITuple {
private readonly T1 m_Item1;
private readonly T2 m_Item2;
private readonly T3 m_Item3;
public T1 Item1 { get { return m_Item1; } }
public T2 Item2 { get { return m_Item2; } }
public T3 Item3 { get { return m_Item3; } }
public Tuple(T1 item1, T2 item2, T3 item3) {
m_Item1 = item1;
m_Item2 = item2;
m_Item3 = item3;
public override Boolean Equals(Object obj) {
return ((IStructuralEquatable) this).Equals(obj, EqualityComparer<Object>.Default);;
Boolean IStructuralEquatable.Equals(Object other, IEqualityComparer comparer) {
if (other == null) return false;
Tuple<T1, T2, T3> objTuple = other as Tuple<T1, T2, T3>;
if (objTuple == null) {
return false;
return comparer.Equals(m_Item1, objTuple.m_Item1) && comparer.Equals(m_Item2, objTuple.m_Item2) && comparer.Equals(m_Item3, objTuple.m_Item3);
Int32 IComparable.CompareTo(Object obj) {
return ((IStructuralComparable) this).CompareTo(obj, Comparer<Object>.Default);
Int32 IStructuralComparable.CompareTo(Object other, IComparer comparer) {
if (other == null) return 1;
Tuple<T1, T2, T3> objTuple = other as Tuple<T1, T2, T3>;
if (objTuple == null) {
throw new ArgumentException(Environment.GetResourceString("ArgumentException_TupleIncorrectType", this.GetType().ToString()), "other");
int c = 0;
c = comparer.Compare(m_Item1, objTuple.m_Item1);
if (c != 0) return c;
c = comparer.Compare(m_Item2, objTuple.m_Item2);
if (c != 0) return c;
return comparer.Compare(m_Item3, objTuple.m_Item3);
public override int GetHashCode() {
return ((IStructuralEquatable) this).GetHashCode(EqualityComparer<Object>.Default);
Int32 IStructuralEquatable.GetHashCode(IEqualityComparer comparer) {
return Tuple.CombineHashCodes(comparer.GetHashCode(m_Item1), comparer.GetHashCode(m_Item2), comparer.GetHashCode(m_Item3));
Int32 ITuple.GetHashCode(IEqualityComparer comparer) {
return ((IStructuralEquatable) this).GetHashCode(comparer);
public override string ToString() {
StringBuilder sb = new StringBuilder();
sb.Append("(");
return ((ITuple)this).ToString(sb);
string ITuple.ToString(StringBuilder sb) {
sb.Append(m_Item1);
sb.Append(", ");
sb.Append(m_Item2);
sb.Append(", ");
sb.Append(m_Item3);
sb.Append(")");
return sb.ToString();
int ITuple.Size {
get {
return 3;
}
如果您的消费代码可以使用IDictionary<>接口,而不是字典,我的直觉是使用带有自定义数组比较器的SortedDictionary<>,即:
class ArrayComparer<T> : IComparer<IList<T>>
where T : IComparable<T>
public int Compare(IList<T> x, IList<T> y)
int compare = 0;
for (int n = 0; n < x.Count && n < y.Count; ++n)
compare = x[n].CompareTo(y[n]);
return compare;
}
并创建如下内容(仅出于具体示例的目的使用int[] ):
var dictionary = new SortedDictionary<int[], string>(new ArrayComparer<int>());
如果您使用的是C# 7,则应该考虑使用值元组作为组合键。值元组通常比传统的引用元组(
Tuple<T1, …>
)提供更好的性能,因为值元组是值类型(结构),而不是引用类型,因此它们避免了内存分配和垃圾收集成本。此外,它们提供了更简洁、更直观的语法,如果您愿意的话,可以对它们的字段进行命名。它们还实现了字典所需的
IEquatable<T>
接口。
var dict = new Dictionary<(int PersonId, int LocationId, int SubjectId), string>();
dict.Add((3, 6, 9), "ABC");
dict.Add((PersonId: 4, LocationId: 9, SubjectId: 10), "XYZ");
var personIds = dict.Keys.Select(k => k.PersonId).Distinct().ToList();