字典中的key为数组,在查找的时候如何操作?

anthony1119 2018-02-05 09:23:38
例如声明一个字典类型的变量,key为int[]类型,往字典中添加时,通过Dictionary.Add(new[]{i,i}, i^2)的方式添加,那么在调用这个字典中的成员时如果我使用Dictionary[new[]{1,1}]的方式查找,会报给定关键字不在字典中的错误。这个有什么比较好的解决办法吗?
...全文
735 16 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
比如说: index hashcode next -------- ------------- ------- 0 122342388 3 1 8398sf8283 0 ....... 它是这样的数组,同时又有 next 链接来表示子节点。
  • 打赏
  • 举报
回复
Dictionary<,> 内部结构是一个类似于树同时又类似于数组的结构,随便贴一段代码
private int FindEntry(TKey key)
{
	if (key == null)
	{
		ThrowHelper.ThrowArgumentNullException(ExceptionArgument.key);
	}
	if (this.buckets != null)
	{
		int num = this.comparer.GetHashCode(key) & int.MaxValue;
		for (int i = this.buckets[num % this.buckets.Length]; i >= 0; i = this.entries[i].next)
		{
			if (this.entries[i].hashCode == num && this.comparer.Equals(this.entries[i].key, key))
			{
				return i;
			}
		}
	}
	return -1;
}
anthony1119 2018-02-08
  • 打赏
  • 举报
回复
引用 13 楼 sp1234 的回复:
[quote=引用 10 楼 anthony1119 的回复:] 以上代码测试可行,但是单步调试发现字典d中的两个Key中的值均为{0, 1, 1},并且d[new[] {0, 1, 1}]得到的值为2 请问该方法是不是还有地方需要完善? 你打开 Dictionary<,> 的源代码看看当 key 为自定义对象的时候人家是如何索引的,就知道原因了。 专业开发人员学习 .net 基础知识必须从源代码入手。
感谢指点,学习完之后还有疑问会继续请教
  • 打赏
  • 举报
回复
引用 10 楼 anthony1119 的回复:
以上代码测试可行,但是单步调试发现字典d中的两个Key中的值均为{0, 1, 1},并且d[new[] {0, 1, 1}]得到的值为2 请问该方法是不是还有地方需要完善? @正怒月神
你打开 Dictionary<,> 的源代码看看当 key 为自定义对象的时候人家是如何索引的,就知道原因了。 专业开发人员学习 .net 基础知识必须从源代码入手。
anthony1119 2018-02-07
  • 打赏
  • 举报
回复
引用 11 楼 hanjun0612 的回复:
[quote=引用 10 楼 anthony1119 的回复:] [quote=引用 9 楼 qq_25095899 的回复:] 你这个有bug啊,两个一样的数组 int[] a = { 1, 2, 3 };但对于的值又不一样, 你怎么加到字典里呢
是的,我用1#2#的方法,发现了一个问题, 使用2#提供的代码

static void Main(string[] args)
{
    //测试数据
    Dictionary<int[], string> d = new Dictionary<int[], string>(new ArrEqualityComparer());
    int[] a = {1, 1, 1};
    d.Add(a, “1”);
    a[0] = 0;
    d.Add(a, “2”);
}
以上代码测试可行,但是单步调试发现字典d中的两个Key中的值均为{0, 1, 1},并且d[new[] {0, 1, 1}]得到的值为2 请问该方法是不是还有地方需要完善? @正怒月神[/quote] 没相处太好的办法。 不过我觉得你为何不存储一个 string.Join(",",a); 的字符串。类似 "1,2,3"当做key呢? [/quote] @正怒月神 谢谢 用字符串代替int[]是个好办法,后来我也是这样实现的
正怒月神 2018-02-07
  • 打赏
  • 举报
回复
引用 10 楼 anthony1119 的回复:
[quote=引用 9 楼 qq_25095899 的回复:] 你这个有bug啊,两个一样的数组 int[] a = { 1, 2, 3 };但对于的值又不一样, 你怎么加到字典里呢
是的,我用1#2#的方法,发现了一个问题, 使用2#提供的代码

static void Main(string[] args)
{
    //测试数据
    Dictionary<int[], string> d = new Dictionary<int[], string>(new ArrEqualityComparer());
    int[] a = {1, 1, 1};
    d.Add(a, “1”);
    a[0] = 0;
    d.Add(a, “2”);
}
以上代码测试可行,但是单步调试发现字典d中的两个Key中的值均为{0, 1, 1},并且d[new[] {0, 1, 1}]得到的值为2 请问该方法是不是还有地方需要完善? @正怒月神[/quote] 没相处太好的办法。 不过我觉得你为何不存储一个 string.Join(",",a); 的字符串。类似 "1,2,3"当做key呢?
anthony1119 2018-02-07
  • 打赏
  • 举报
回复
引用 9 楼 qq_25095899 的回复:
你这个有bug啊,两个一样的数组 int[] a = { 1, 2, 3 };但对于的值又不一样, 你怎么加到字典里呢
是的,我用1#2#的方法,发现了一个问题, 使用2#提供的代码

static void Main(string[] args)
{
    //测试数据
    Dictionary<int[], string> d = new Dictionary<int[], string>(new ArrEqualityComparer());
    int[] a = {1, 1, 1};
    d.Add(a, “1”);
    a[0] = 0;
    d.Add(a, “2”);
}
以上代码测试可行,但是单步调试发现字典d中的两个Key中的值均为{0, 1, 1},并且d[new[] {0, 1, 1}]得到的值为2 请问该方法是不是还有地方需要完善? @正怒月神
anthony1119 2018-02-06
  • 打赏
  • 举报
回复
引用 5 楼 mkbaoquan 的回复:
老兄我觉得你换个思路吧,你这真是艺高人胆大啊 。你那是个可变数组 你怎么 找啊 。你先用一个KEY 吧数组放进去,然后在放一下数值相对应的 VALUE 、这样就是会多一个中间变量 。你那样搞真的不好操作啊 ,而且你并不能保证你的KEY 是唯一的 。
@Jason_Mao1 是1#2#的方法有什么弊端吗?
大然然 2018-02-06
  • 打赏
  • 举报
回复
你这个有bug啊,两个一样的数组 int[] a = { 1, 2, 3 };但对于的值又不一样, 你怎么加到字典里呢
threenewbee 2018-02-05
  • 打赏
  • 举报
回复
默认比较的是引用,所以数组不适合作为key
Jason_Mao1 2018-02-05
  • 打赏
  • 举报
回复
老兄我觉得你换个思路吧,你这真是艺高人胆大啊 。你那是个可变数组 你怎么 找啊 。你先用一个KEY 吧数组放进去,然后在放一下数值相对应的 VALUE 、这样就是会多一个中间变量 。你那样搞真的不好操作啊 ,而且你并不能保证你的KEY 是唯一的 。
秋的红果实 2018-02-05
  • 打赏
  • 举报
回复
各位! 还可以将你的数组key封装到一个class,然后让class重载==运算符,这样你的key还是“一个整体”
xuzuning 2018-02-05
  • 打赏
  • 举报
回复
C# 没有给 int[] 设计比较相等的方法,因此你需要自己给出。#2 的代码就是的 当然,你也可以弄的再宽松些 将 public bool Equals(int[] b1, int[] b2) 方法体写作 return b1.Except(b2).Count() == 0; 这样 new [] {1, 2} 和 new [] {2, 1} 就可视为相等的了
anthony1119 2018-02-05
  • 打赏
  • 举报
回复
@正怒月神 @巴士上的邂逅 解决了,非常感谢!
正怒月神 2018-02-05
  • 打赏
  • 举报
回复
1楼说的没错
static void Main(string[] args)
        {
            //测试数据
            Dictionary<int[], string> d = new Dictionary<int[], string>(new ArrEqualityComparer());
            int[] a = { 1, 2, 3 };
            string b = "hello";
            d.Add(a, b);

            //使用新实例的 key查找
            int[] a1 = { 1, 2, 3 };
            Console.WriteLine(d[a1]);

            Console.ReadLine();
        }

        //重写key的判断方法
        public class ArrEqualityComparer : IEqualityComparer<int[]>
        {
            public bool Equals(int[] b1, int[] b2)
            {
                bool result = true;
                for (int i = 0; i < b1.Length; i++)
                {
                    if (b1[i] != b2[i])
                    {
                        result = false;
                        break;
                    }
                    
                }
                return result;
            }

            public int GetHashCode(int[] arr)
            {
                int hCode = arr.Sum();
                return hCode.GetHashCode();
            }
        }
巴士上的邂逅 2018-02-05
  • 打赏
  • 举报
回复
你实例化dictionary时试试这个
//
        // 摘要:
        //     初始化 System.Collections.Generic.Dictionary<TKey,TValue> 类的新实例,该实例为空且具有默认的初始容量,并使用指定的
        //     System.Collections.Generic.IEqualityComparer<T>。
        //
        // 参数:
        //   comparer:
        //     比较键时要使用的 System.Collections.Generic.IEqualityComparer<T> 实现,或者为 null,以便为键类型使用默认的
        //     System.Collections.Generic.EqualityComparer<T>。
        public Dictionary(IEqualityComparer<TKey> comparer);

111,098

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • AIGC Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧