请问,Enumerable.Intersect取交集,为什么不成功?

fsdvf34 2011-10-24 11:22:53
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);

取两个集合的交集,为什么没有交集,不是有一个元素是相同的吗?
...全文
1026 27 打赏 收藏 转发到动态 举报
写回复
用AI写文章
27 条回复
切换为时间正序
请发表友善的回复…
发表回复
fsdvf34 2011-10-24
  • 打赏
  • 举报
回复
原来是GetHashCode方法写错了,

public int GetHashCode(List<string> DF)
{
return DF.GetHashCode();
}

请问,GetHashCode方法这样写,为什么就不行呢?
fsdvf34 2011-10-24
  • 打赏
  • 举报
回复
请教5楼代码,哪里错了啊
风骑士之怒 2011-10-24
  • 打赏
  • 举报
回复

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
fsdvf34 2011-10-24
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 dongxinxi 的回复:]

应该可以的吧
虽然你的比较器实现等并不严密(比如有重复元素),但对于你上面的测试数据,还是可以取到第一个元素交集的
[/Quote]
事实上,不行啊
  • 打赏
  • 举报
回复
应该可以的吧
虽然你的比较器实现等并不严密(比如有重复元素),但对于你上面的测试数据,还是可以取到第一个元素交集的
fsdvf34 2011-10-24
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 dongxinxi 的回复:]

引用 4 楼 wknight_it 的回复:
实现IEqualityComparer<string>接口,自己写个比较


是的,你要比较的是两个List<string>,引用类型,只是他们包含的元素完全相同罢了,但运行时它们是两个完全独立的对象
[/Quote]
5楼,实现类了IEqualityComparer接口,为什么还是不行呢?
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 wknight_it 的回复:]
实现IEqualityComparer<string>接口,自己写个比较
[/Quote]

是的,你要比较的是两个List<string>,引用类型,只是他们包含的元素完全相同罢了,但运行时它们是两个完全独立的对象
fsdvf34 2011-10-24
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 stonespace 的回复:]

如果真要比较,你应该把List<string>封装一个类,然后实现接口IEquatable的Equals方法,最好也顺便实现Object.Equals方法,

或者调用另一个版本的Intersect,传入EqualityComparer对象,这样你还是要创建一个类,实现EqualityComparer,比较麻烦,
[/Quote]
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();
}
}

那这样呢,我写了个自定义的比较器,但还是不行呢?
风骑士之怒 2011-10-24
  • 打赏
  • 举报
回复
实现IEqualityComparer<string>接口,自己写个比较
萧炎 2011-10-24
  • 打赏
  • 举报
回复

//取交集
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]);
}
}
}
stonespace 2011-10-24
  • 打赏
  • 举报
回复
如果真要比较,你应该把List<string>封装一个类,然后实现接口IEquatable的Equals方法,最好也顺便实现Object.Equals方法,

或者调用另一个版本的Intersect,传入EqualityComparer对象,这样你还是要创建一个类,实现EqualityComparer,比较麻烦,
stonespace 2011-10-24
  • 打赏
  • 举报
回复
c#不知道如何判断两个List<string>是否相等,因为List<string>没有提供Equals的实现,c#默认为比较引用,两个List<string>的内容虽然相同,但是两次new,存储空间不一样,比较引用自然不一样,

jianshao810 2011-10-24
  • 打赏
  • 举报
回复
啊 飞 确实 很厉害。顶一个。
传入EqualityComparer对象,这样解决方案比较好。
threenewbee 2011-10-24
  • 打赏
  • 举报
回复
这个问题,我在http://topic.csdn.net/u/20111024/21/be44a7d1-2eda-4905-8295-73f8bc17ab5b.html回答你了。

GetHashCode一般没有必要自己写。尽量利用现有代码的GetHashCode

思路,相同的string的HashCode是相等的,相等的值类型也相等。所以,你要考虑的是构造一个值类型(结构体或者字符串,或者简单类型),使得相等的值有唯一的表示,不等的值有不等的表示,然后调用它的 GetHashCode 即可。
  • 打赏
  • 举报
回复
误会,测试数据不一样
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 fsdvf34 的回复:]
请教5楼代码,哪里错了啊
[/Quote]

我在VS2010用5#的代码测试了下,可以取到的
jshi123 2011-10-24
  • 打赏
  • 举报
回复
统一返回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比较。
阿非 2011-10-24
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 fsdvf34 的回复:]
那引用类型的GetHashCode方法该怎么写啊,谁知道它的哈希值是多少呢?统一写成return 0;要得吗?
[/Quote]

GetHashCode 需要你自己提供的 就是override ,如果你不提供则会使用默认的 Object的GetHashCode 方法
风骑士之怒 2011-10-24
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 fsdvf34 的回复:]
引用 18 楼 sandy945 的回复:

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

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

根据你Equal方法里面涉及到该引用类型的相关操作做一个哈希值统计,

PS:11L的哈希值统计不好,请参考阿非的GetHashCode
加载更多回复(7)
目录 1 LINQ查询结果集 1 2 System.Array 数组 1 2.1 基于System.Array定义数组 1 2.2 基于类型定义数组 1 2.3 数组元素的清空 1 2.4 System.Array类静态成员 1 2.5 不用循环填充数组 1 2.6 数组类实例成员 2 3 System.Collections 集合 2 3.1 ArrayList 2 3.1.1 实例成员 2 3.1.2 静态成员 2 3.2 List 3 3.3 Hashtable 6 3.4 SortedList 6 3.5 SortedList 7 3.6 Queue 8 3.7 Stack 8 3.8 LinkedList 8 3.9 HashSet 9 4 System.Linq 10 4.1 System.Linq.Enumerable 10 4.2 System.Linq.Queryable 10 4.3 System.Linq.Lookup 10 4.4 System.Linq.Expressions.Expression 10 5 接口 10 5.1 IEnumerable 、IEnumerator 10 5.1.1 正常使用 10 5.1.2 C#的 yield 12 5.2 IEnumerable 12 5.3 IEnumerator 12 5.4 ICollection 12 5.5 ICollection 13 5.6 IList 13 5.7 IList 13 5.8 IEqualityComparer 13 5.9 IEqualityComparer 13 5.10 IDictionary 13 5.11 IDictionary 13 5.12 IDictionaryEnumerator 13 5.13 IComparer 13 5.13.1 接口方法说明 int Compare(object x, object y) 13 5.13.2 ArrayList.Sort (IComparer) 方法 13 5.14 IComparer 14 5.14.1 接口方法override int Compare(T x, T y)说明 14 5.14.2 List.Sort (IComparer) 方法 14 5.15 System.Linq.IGrouping 14 5.16 System.Linq.ILookup 14 5.17 System.Linq.IOrderedEnumerable 14 5.18 System.Linq.IOrderedQueryable 14 5.19 System.Linq.IOrderedQueryable 15 5.20 System.Linq.IQueryable 15 5.21 System.Linq.IQueryable 15 5.22 System.Linq.IQueryProvider 15 6 集合扩展方法 15 6.1 集合扩展方法的实现:一个Where的例子 15 6.2 延迟类 15 6.2.1 Select 选择 16 6.2.2 SelectMany 选择 16 6.2.3 Where 条件 16 6.2.4 OrderBy 排序升 17 6.2.5 OrderByDescending 排序降 17 6.2.6 GroupBy 分组 17 6.2.7 Join 联合查询 18 6.2.8 GroupJoin 18 6.2.9 Take 获集合的前n个元素 19 6.2.10 Skip 跳过集合的前n个元素 19 6.2.11 Distinct 过滤集合中的相同项 19 6.2.12 Union 连接不同集合,自动过滤相同项 19 6.2.13 Concat 连接不同集合,不会自动过滤相同项 19 6.2.14 Intersect不同集合的相同项(交集) 20 6.2.15 Except 从某集合中删除其与另一个集合中相同的项 20 6.2.16 Reverse 反转集合 20 6.2.17 TakeWhile 条件第一次不成立就跳出循环 20 6.2.18 SkipWhile 条件第一次不成立就失效,将后面的数据全 20 6.2.19 Cast 将集合转换为强类型集合 21 6.2.20 OfType 过滤集合中的指定类型 21 6.3 不延迟(浅复本) 21 6.3.1 Single 集合中符合条件的唯一元素,浅复本 21 6.3.2 SingleOrDefault 集合中符合条件的唯一元素(没有则返回类型默认值),浅复本 21 6.3.3 First 集合的第一个元素,浅复本 21 6.3.4 FirstOrDefault 集合中的第一个元素(没有则返回类型默认值),浅复本 22 6.3.5 Last 集合中的最后一个元素,浅复本 22 6.3.6 LastOrDefault 集合中的最后一个元素(没有则返回类型默认值),浅复本 22 6.3.7 ElementAt 集合中指定索引的元素,浅复本 22 6.3.8 ElementAtOrDefault 集合中指定索引的元素(没有则返回类型默认值),浅复本 22 6.3.9 Contains 判断集合中是否包含有某一元素 22 6.3.10 Any 判断集合中是否有元素满足某一条件 22 6.3.11 All 判断集合中是否所有元素都满足某一条件 23 6.3.12 SequenceEqual 判断两个集合内容是否相同 23 6.3.13 Count 、LongCount集合中的元素个数 23 6.3.14 Average 、Sum集合平均值求和 23 6.3.15 Max、Min 集合最大值,最小值 24 6.3.16 Aggregate 根据输入的表达式获一个聚合值 24 6.3.17 DefaultIfEmpty 查询结果为空则返回默认值,浅复本 24 6.3.18 ToArray 将集合转换为数组,浅复本 24 6.3.19 ToList 将集合转换为List集合,浅复本 25 6.3.20 ToDictionary 将集合转换为集合,浅复本 25 7 Lambda表达式 25 7.1 例1(比效) 25 7.2 例2(多参) 27 7.3 例3(list.Where) 27 7.4 Lambda表达式中Lifting 28 8 QuerySyntax 查询语法 29 8.1 from in select 30 8.2 orderby 排序 30 8.3 group by into 分组 31 8.4 join in on equals 联合查询 33 8.5 into 汇总 33 9 DataSource 数据绑定 34

110,546

社区成员

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

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

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