List<List<string>> lis1_比较 = new List<List<string>>() 
            { 
                new List<string>() { "0", "1", "2" },
                new List<string>() { "0", "3", "4" }
            };List<List<string>> lis2_比较 = new List<List<string>>() 
            {
                new List<string>() { "0", "1" ,"2"},
                new List<string>() { "4", "5" }
            };List<List<string>> lis1_结果 = Enumerable.Intersect(lis1_比较, lis2_比较).ToList(); //取交集
Console.WriteLine(lis1_结果.Count);取两个集合的交集,为什么没有交集,不是有一个元素是相同的吗?

解决方案 »

  1.   

    c#不知道如何判断两个List<string>是否相等,因为List<string>没有提供Equals的实现,c#默认为比较引用,两个List<string>的内容虽然相同,但是两次new,存储空间不一样,比较引用自然不一样,
      

  2.   

    如果真要比较,你应该把List<string>封装一个类,然后实现接口IEquatable的Equals方法,最好也顺便实现Object.Equals方法,或者调用另一个版本的Intersect,传入EqualityComparer对象,这样你还是要创建一个类,实现EqualityComparer,比较麻烦,
      

  3.   


      //取交集
      ArrayList   al=new   ArrayList(); 
      ArrayList al1=new ArrayList(); 
      ArrayList al2=new ArrayList(); 
      int   i; 
      for(i=0;i <10;i++) 
      { 
       al.Add(i); 
      } 
      for(i=5;i <20;i++) 
      { 
        al1.Add(i); 
      } 
      for(i=0;i <al.Count;i++) 
      { 
       if(al1.Contains(al[i])) 
       { 
        al2.Add(al[i]); 
       } 
      }
    }
      

  4.   

    实现IEqualityComparer<string>接口,自己写个比较 
      

  5.   

    class Example
        {
            static void Main()
            {
                myeqc c = new myeqc();
                List<List<string>> lis1_比较 = new List<List<string>>() 
                { 
                    new List<string>() { "0", "1", "2" },
                    new List<string>() { "0", "3", "4" }
                };
                List<List<string>> lis2_比较 = new List<List<string>>() 
                {
                    new List<string>() { "0", "1" ,"2"},
                     new List<string>() { "4", "5" }
                };
                List<List<string>> lis1_结果 = Enumerable.Intersect(lis1_比较, lis2_比较,c).ToList();
                Console.WriteLine(lis1_结果.Count);            
                Console.ReadKey();
            }
        }
        class myeqc : IEqualityComparer<List<string>>  //自定义相等比较器
        {
            public bool Equals(List<string> list1, List<string> list2)
            {
                int i = 0;    //看看两个集合有多少个元素相同
                foreach (string s in list1)
                {
                    foreach (string s2 in list2)
                    {
                        if (s == s2)
                            i++;
                    }
                }
                if (i == list1.Count && i == list2.Count)
                {
                    return true;
                }
                else
                {
                    return false;
                }
            }            public int GetHashCode(List<string> DF)
            {
                return DF.GetHashCode();
            }
        }那这样呢,我写了个自定义的比较器,但还是不行呢?
      

  6.   


    是的,你要比较的是两个List<string>,引用类型,只是他们包含的元素完全相同罢了,但运行时它们是两个完全独立的对象
      

  7.   

    5楼,实现类了IEqualityComparer接口,为什么还是不行呢?
      

  8.   

    参考:http://blog.csdn.net/q107770540/article/details/6371087
      

  9.   


    public class MyComparer : IEqualityComparer<List<string>>
        {
            public bool Equals(List<string> x, List<string> y)
            {
                if (x.Count != y.Count) return false;
                for (int i = 0, c = x.Count; i < c; i++)
                {
                    if (!x[i].Equals(y[i]))
                    {
                        return false;
                    }
                }
                return true;
            }        public int GetHashCode(List<string> obj)
            {
                if (Object.ReferenceEquals(obj, null)) return 0;
                int code = 0;
                foreach (string item in obj)
                {
                    code ^= item.GetHashCode();
                }
                return code;
            }
        }    class Program
        {
            static void Main(string[] args)
            {
                List<List<string>> list1 = new List<List<string>>() { 
                    new List<string>(){ "3", "1", "3" },
                    new List<string>(){ "1", "2" },
                    new List<string>(){ "0", "1", "2","4" }
                };            List<List<string>> list2 = new List<List<string>>() { 
                    new List<string>(){ "0", "1", "2","4" },
                    new List<string>(){ "0", "1", "3" },
                    new List<string>(){ "2", "1" }
                };            List<List<string>> result = Enumerable.Intersect(list1, list2, new MyComparer()).ToList();
                foreach (List<string> item in result)
                {
                    Console.WriteLine("item:");
                    foreach (string sub in item)
                    {
                        Console.WriteLine(sub);
                    }
                }
                Console.Read();
            }
        }
    result:
    item:
    0
    1
    2
    4
      

  10.   

    原来是GetHashCode方法写错了, public int GetHashCode(List<string> DF)
            {
                return DF.GetHashCode();
            }请问,GetHashCode方法这样写,为什么就不行呢?
      

  11.   

    return DF.ToString().GetHashCode();
      

  12.   

    不是已经有一个bool返回值了吗?这个返回值,到哪里去了呢
      

  13.   


    public class CustomEqualityComparer : IEqualityComparer<List<string>>
        {
            public bool Equals(List<string> x, List<string> y)
            {
                //x==y==null
                if (x == y)
                    return true;
                if (x == null)
                    return false;
                if (y == null)
                    return false;
                if (x.Count != y.Count)
                    return false;
                for (int i = 0, count = x.Count; i < count; i++)
                {
                    if (x[i] != y[i])
                        return false;
                }
                return true;
                //throw new NotImplementedException();
            }        public int GetHashCode(List<string> obj)
            {
                if (obj == null)
                    return 0;            int hash = 17;
                hash = (hash * 3) + obj.Count.GetHashCode();
                foreach (string str in obj)
                {
                    hash = (hash * 3) + str.GetHashCode();
                }
                return hash;
                //throw new NotImplementedException();
            }
        }
      

  14.   

    DF 是引用类型,不同的引用类型实例的GetHashCode 也是不同的
      

  15.   


    请查看.NET类库的 Enumerable的Intersect方法 HashSet<T>的Add方法大概如下:public static IEnumerable<TSource> Intersect<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
            {
                if (first == null)
                {
                    throw Error.ArgumentNull("first");
                }
                if (second == null)
                {
                    throw Error.ArgumentNull("second");
                }
                return IntersectIterator<TSource>(first, second, comparer);
            }        private static IEnumerable<TSource> IntersectIterator<TSource>(IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
            {
                Set<TSource> iteratorVariable0 = new Set<TSource>(comparer);
                foreach (TSource local in second)
                {
                    iteratorVariable0.Add(local);
                }
                foreach (TSource iteratorVariable1 in first)
                {
                    if (!iteratorVariable0.Remove(iteratorVariable1))
                    {
                        continue;
                    }
                    yield return iteratorVariable1;
                }
            }
    如果iteratorVariable0.Add(local);这里添加不进去元素,你说你能取到什么交集Set<TSource> iteratorVariable0 = new Set<TSource>(comparer);这里以IEqualityComparer接口的一个实例变量来初始化一个Set集合变量关于Add方法,看这里:public bool Add(T item)
            {
                return this.AddIfNotPresent(item);
            }        private bool AddIfNotPresent(T value)
            {
                int freeList;
                if (this.m_buckets == null)
                {
                    this.Initialize(0);
                }
                int hashCode = this.InternalGetHashCode(value);
                int index = hashCode % this.m_buckets.Length;
                for (int i = this.m_buckets[hashCode % this.m_buckets.Length] - 1; i >= 0; i = this.m_slots[i].next)
                {
                    if ((this.m_slots[i].hashCode == hashCode) && this.m_comparer.Equals(this.m_slots[i].value, value))
                    {
                        return false;
                    }
                }
                if (this.m_freeList >= 0)
                {
                    freeList = this.m_freeList;
                    this.m_freeList = this.m_slots[freeList].next;
                }
                else
                {
                    if (this.m_lastIndex == this.m_slots.Length)
                    {
                        this.IncreaseCapacity();
                        index = hashCode % this.m_buckets.Length;
                    }
                    freeList = this.m_lastIndex;
                    this.m_lastIndex++;
                }
                this.m_slots[freeList].hashCode = hashCode;
                this.m_slots[freeList].value = value;
                this.m_slots[freeList].next = this.m_buckets[index] - 1;
                this.m_buckets[index] = freeList + 1;
                this.m_count++;
                this.m_version++;
                return true;
            }
    private int InternalGetHashCode(T item)
            {
                if (item == null)
                {
                    return 0;
                }
                return (this.m_comparer.GetHashCode(item) & 0x7fffffff);
            }
     int hashCode = this.InternalGetHashCode(value);

    this.m_comparer.GetHashCode(item)这两句,可以发现集合列表的Add方法和该接口所实现的GetHashCode函数息息相关,其实这里,你应该就能明白,为什么该接口的一个实现类,他的GetHashCode能影响这个比较,因为其内部的集合Add元素,会先取该元素的hashcode
      

  16.   

    那引用类型的GetHashCode方法该怎么写啊,谁知道它的哈希值是多少呢?统一写成return 0;要得吗?
      

  17.   


    根据你Equal方法里面涉及到该引用类型的相关操作做一个哈希值统计,PS:11L的哈希值统计不好,请参考阿非的GetHashCode
      

  18.   


    GetHashCode 需要你自己提供的 就是override ,如果你不提供则会使用默认的 Object的GetHashCode 方法
      

  19.   

    统一返回0,也是可以工作的,但这样效率很低。
    运行时,会先调用GetHashCode获取每个字符串列表的散列值,如果它们不同,就不会调用Equals进行比较,只有散列值相同的情况下,才会用Equals进行比较。
    下面的方法加上了一些输出语句,你可以看到方法被调用的过程:class myeqc : IEqualityComparer<List<string>> //自定义相等比较器
    {
    public bool Equals(List<string> list1, List<string> list2)
    {
    int i = 0; //看看两个集合有多少个元素相同
    foreach (string s in list1)
    {
    foreach (string s2 in list2)
    {
    if (s == s2)
    i++;
    }
    }
    Console.WriteLine("正在比较:[{0}] 和 [{1}]", string.Join(",", list1.ToArray()), string.Join(",", list2.ToArray()));
    Console.WriteLine("结果:{0}, 共{1}个元素,其中{2}个相同", i == list1.Count && i == list2.Count, Math.Max(list1.Count, list2.Count), i);
    Console.WriteLine();
    if (i == list1.Count && i == list2.Count)
    {
    return true;
    }
    else
    {
    return false;
    }
    } public int GetHashCode(List<string> DF)
    {
    int hash = 0;
    Console.WriteLine("正在获取[{0}]的哈希值,返回{1}", string.Join(", ",DF.ToArray()), hash);
    return hash;
    }
    }可以看到:如果返回的哈希值是0,一共执行4次比较,而改成:
    int hash = DF.GetHashCode();
    则因为所有的散列值都不同,所以一直比较也没执行,直接被认为没有相同的字符串列表。
    如果改成:
    int hash = DF.Aggregate(0, (h, s) => 32 * h + s.GetHashCode());
    则一共只进行一次Equals比较。
      

  20.   

    这个问题,我在http://topic.csdn.net/u/20111024/21/be44a7d1-2eda-4905-8295-73f8bc17ab5b.html回答你了。GetHashCode一般没有必要自己写。尽量利用现有代码的GetHashCode思路,相同的string的HashCode是相等的,相等的值类型也相等。所以,你要考虑的是构造一个值类型(结构体或者字符串,或者简单类型),使得相等的值有唯一的表示,不等的值有不等的表示,然后调用它的 GetHashCode 即可。
      

  21.   

    啊 飞 确实 很厉害。顶一个。
    传入EqualityComparer对象,这样解决方案比较好。