C# LINQ intersect,一个对象的多个列表,一些为空
我想找一个和LINQ相交的地方 我有这样的目标:C# LINQ intersect,一个对象的多个列表,一些为空,c#,linq,C#,Linq,我想找一个和LINQ相交的地方 我有这样的目标: public class objA { public int foo1{ get; set; } public string foo2 { get; set; } public bool foo3 { get; set; } } 样本: List<objA> name1= new List<int>() {{1,"bb",true} , {2,"cc",false}}; List<
public class objA
{
public int foo1{ get; set; }
public string foo2 { get; set; }
public bool foo3 { get; set; }
}
样本:
List<objA> name1= new List<int>() {{1,"bb",true} , {2,"cc",false}};
List<objA> name2= new List<int>();
List<objA> name3= new List<int>() { {1,"bb",true} };
List<objA> name4= new List<int>() { {1,"bb",true} , {2,"cc",false} };
List<objA> name5= new List<int>() { {1,"bb",true} };
List name1=newlist(){{1,“bb”,true},{2,“cc”,false};
列表名称2=新列表();
List name3=新列表(){{1,“bb”,true};
列表名称4=新列表(){{1,“bb”,true},{2,“cc”,false};
列表名5=新列表(){{1,“bb”,true};
要返回:{1,“bb”,true},因为它存在于所有列表中。。如果我跑步:
List<objA>= name1
.Intersect(name2)
.Intersect(name3)
.Intersect(name4)
.Intersect(name5).ToList();
List=name1
.Intersect(名称2)
.Intersect(名称3)
.Intersect(名称4)
.Intersect(名称5.ToList();
它不返回任何内容,因为列表2为空
public static class Ex
{
public static IEnumerable<T> IntersectIgnoreEmpty<T>(this IEnumerable<T> @this, IEnumerable<T> other, IEqualityComparer<T> comparer)
{
return other.Any() ? @this.Intersect(other, comparer) : @this;
}
}
我知道这个信息:
但是我不知道如何处理对象。同样的方法:
public IEnumerable<T> IntersectsNonEmpty<T>(
params IEnumerable<T>[] input)
{
var nonEmpty = input.Where(i => i.Any()).ToList();
if (!nonEmpty.Any()) return false; //or whatever
return nonEmpty.Aggregate((l1, l2) => l1.Intersect(l2));
}
首先,name2是空的。“交集”总是一无所获。所以删除name2
List<objA> output = name1
.Intersect(name3)
.Intersect(name4)
.Intersect(name5).ToList();
这是因为“相交”使用“相等”来比较对象。
它使用“GetHashCode”来加速。空结果的原因是name2 list empty。如果在name2中添加{1,“bb”,true},则结果将不会为空。如果您想准确理解代码不工作的原因,那么Tommy的答案是完美的-删除“.Intersect(name2)”行(因为“name2”没有任何项,因此与它相交将始终返回零结果),然后在“objA”类上实现GetHashCode和Equals方法 但是,如果您只想让代码以最简单的方式工作,那么可以将objA从类更改为结构,因为结构会自动接收GetHashCode并等于实现您想要的功能 我已经修复了您的原始代码,以便它编译并将“objA”更改为一个结构,现在最终的“x”值将是一个具有单个值的列表(foo1=1,foo2=“bb”,foo3=true)
使用System.Collections.Generic;
使用System.Linq;
命名空间StackOverflowAnswer
{
公共结构objA
{
公共int foo1{get;set;}
公共字符串foo2{get;set;}
公共bool foo3{get;set;}
}
班级计划
{
静态void Main()
{
List name1=new List(){new objA{foo1=1,foo2=“bb”,foo3=true},new objA{foo1=2,foo2=“cc”,foo3=false};
列表名称2=新列表();
List name3=new List(){new objA{foo1=1,foo2=“bb”,foo3=true};
列表名称4=new List(){new objA{foo1=1,foo2=“bb”,foo3=true},new objA{foo1=2,foo2=“cc”,foo3=false};
List name5=new List(){new objA{foo1=1,foo2=“bb”,foo3=true};
列表x=name1
//.Intersect(名称2)
.Intersect(名称3)
.Intersect(名称4)
.Intersect(名称5)
.ToList();
}
}
}
在阅读了关于这个问题的其他答案的评论之后,也许我遗漏了部分要点——在执行“交集”时,是否希望有效地忽略空集
如果是这样,那么您可以编写自己的“Intersect”版本来实现这一点,该版本将忽略空集-例如
using System.Collections.Generic;
using System.Linq;
namespace StackOverflowAnswer
{
public struct objA
{
public int foo1 { get; set; }
public string foo2 { get; set; }
public bool foo3 { get; set; }
}
class Program
{
static void Main()
{
List<objA> name1 = new List<objA>() { new objA { foo1 = 1, foo2 = "bb", foo3 = true }, new objA { foo1 = 2, foo2 = "cc", foo3 = false } };
List<objA> name2 = new List<objA>();
List<objA> name3 = new List<objA>() { new objA { foo1 = 1, foo2 = "bb", foo3 = true } };
List<objA> name4 = new List<objA>() { new objA { foo1 = 1, foo2 = "bb", foo3 = true }, new objA { foo1 = 2, foo2 = "cc", foo3 = false } };
List<objA> name5 = new List<objA>() { new objA { foo1 = 1, foo2 = "bb", foo3 = true } };
List<objA> x = name1
.IntersectUnlessEmpty(name2)
.IntersectUnlessEmpty(name3)
.IntersectUnlessEmpty(name4)
.IntersectUnlessEmpty(name5)
.ToList();
}
}
public static class IEnumerableExtensions
{
public static IEnumerable<T> IntersectUnlessEmpty<T>(this IEnumerable<T> source, IEnumerable<T> second)
{
return second.Any() ? source.Intersect(second) : source;
}
}
}
使用System.Collections.Generic;
使用System.Linq;
命名空间StackOverflowAnswer
{
公共结构objA
{
公共int foo1{get;set;}
公共字符串foo2{get;set;}
公共bool foo3{get;set;}
}
班级计划
{
静态void Main()
{
List name1=new List(){new objA{foo1=1,foo2=“bb”,foo3=true},new objA{foo1=2,foo2=“cc”,foo3=false};
列表名称2=新列表();
List name3=new List(){new objA{foo1=1,foo2=“bb”,foo3=true};
列表名称4=new List(){new objA{foo1=1,foo2=“bb”,foo3=true},new objA{foo1=2,foo2=“cc”,foo3=false};
List name5=new List(){new objA{foo1=1,foo2=“bb”,foo3=true};
列表x=name1
.Unlessempty(名称2)
.Unlessempty(名称3)
.Unlessempty(名称4)
.Unlessempty(名称5)
.ToList();
}
}
公共静态类IEnumerableExtensions
{
公共静态IEnumerable IntersectUnlessEmpty(此IEnumerable源,IEnumerable秒)
{
返回second.Any()?source.Intersect(second):source;
}
}
}
在这种情况下,最后的“x”值仍然是一个带有单个项目的列表-空的“名称2”数据并没有阻止非空列表被相交。首先,让我们定义一个扩展方法,该方法将执行相交,但忽略任何空列表
public static class Ex
{
public static IEnumerable<T> IntersectIgnoreEmpty<T>(this IEnumerable<T> @this, IEnumerable<T> other, IEqualityComparer<T> comparer)
{
return other.Any() ? @this.Intersect(other, comparer) : @this;
}
}
然后我们可以运行以下代码:
List<objA> name1 = new List<objA>()
{
new objA { foo1 = 1, foo2 = "bb", foo3 = true },
new objA { foo1 = 2, foo2 = "cc", foo3 = false },
};
List<objA> name2 = new List<objA>();
List<objA> name3 = new List<objA>() { new objA { foo1 = 1, foo2 = "bb", foo3 = true } };
List<objA> name4 = new List<objA>()
{
new objA { foo1 = 1, foo2 = "bb", foo3 = true },
new objA { foo1 = 2, foo2 = "cc", foo3 = false },
};
List<objA> name5 = new List<objA>() { new objA { foo1 = 1, foo2 = "bb", foo3 = true } };
objAEqualityComparer comparer = new objAEqualityComparer();
List<objA> result =
name1
.IntersectIgnoreEmpty(name2, comparer)
.IntersectIgnoreEmpty(name3, comparer)
.IntersectIgnoreEmpty(name4, comparer)
.IntersectIgnoreEmpty(name5, comparer)
.ToList();
List name 1=新列表()
{
新的objA{foo1=1,foo2=“bb”,foo3=true},
新的objA{foo1=2,foo2=“cc”,foo3=false},
};
列表名称2=新列表();
List name3=new List(){new objA{foo1=1,foo2=“bb”,foo3=true};
列表名称4=新列表()
{
新的objA{foo1=1,foo2=“bb”,foo3=true},
新的objA{foo1=2,foo2=“cc”,foo3=false},
};
List name5=new List(){new objA{foo1=1,foo2=“bb”,foo3=true};
objAEqualityComparer comparer=新的objAEqualityComparer();
列表结果=
名称1
.IntersectIgnoreEmpty(名称2,比较器)
.IntersectIgnoreEmpty(名称3,比较器)
.IntersectIgnoreEmpty(名称4,比较器)
.IntersectIgnoreEmpty(名称5,比较器)
.ToList();
我们得到的结果是:
您始终可以在
objA
中覆盖等于和GetHashCode
,但这需要将objA
设置为只读,以免违反平等契约-在这种情况下,设置IEqualityComparer
是一个更好的选择,因为它允许objA
被读/写。您需要覆盖GetHashCode
和等于,并将objA
设置为只读,以获得
using System.Collections.Generic;
using System.Linq;
namespace StackOverflowAnswer
{
public struct objA
{
public int foo1 { get; set; }
public string foo2 { get; set; }
public bool foo3 { get; set; }
}
class Program
{
static void Main()
{
List<objA> name1 = new List<objA>() { new objA { foo1 = 1, foo2 = "bb", foo3 = true }, new objA { foo1 = 2, foo2 = "cc", foo3 = false } };
List<objA> name2 = new List<objA>();
List<objA> name3 = new List<objA>() { new objA { foo1 = 1, foo2 = "bb", foo3 = true } };
List<objA> name4 = new List<objA>() { new objA { foo1 = 1, foo2 = "bb", foo3 = true }, new objA { foo1 = 2, foo2 = "cc", foo3 = false } };
List<objA> name5 = new List<objA>() { new objA { foo1 = 1, foo2 = "bb", foo3 = true } };
List<objA> x = name1
.IntersectUnlessEmpty(name2)
.IntersectUnlessEmpty(name3)
.IntersectUnlessEmpty(name4)
.IntersectUnlessEmpty(name5)
.ToList();
}
}
public static class IEnumerableExtensions
{
public static IEnumerable<T> IntersectUnlessEmpty<T>(this IEnumerable<T> source, IEnumerable<T> second)
{
return second.Any() ? source.Intersect(second) : source;
}
}
}
public static class Ex
{
public static IEnumerable<T> IntersectIgnoreEmpty<T>(this IEnumerable<T> @this, IEnumerable<T> other, IEqualityComparer<T> comparer)
{
return other.Any() ? @this.Intersect(other, comparer) : @this;
}
}
public class objAEqualityComparer : IEqualityComparer<objA>
{
public bool Equals(objA left, objA right)
{
return
left.foo1 == right.foo1
&& left.foo2 == right.foo2
&& left.foo3 == right.foo3;
}
public int GetHashCode(objA @this)
{
return
@this.foo1.GetHashCode()
^ @this.foo2.GetHashCode()
^ @this.foo3.GetHashCode();
}
}
List<objA> name1 = new List<objA>()
{
new objA { foo1 = 1, foo2 = "bb", foo3 = true },
new objA { foo1 = 2, foo2 = "cc", foo3 = false },
};
List<objA> name2 = new List<objA>();
List<objA> name3 = new List<objA>() { new objA { foo1 = 1, foo2 = "bb", foo3 = true } };
List<objA> name4 = new List<objA>()
{
new objA { foo1 = 1, foo2 = "bb", foo3 = true },
new objA { foo1 = 2, foo2 = "cc", foo3 = false },
};
List<objA> name5 = new List<objA>() { new objA { foo1 = 1, foo2 = "bb", foo3 = true } };
objAEqualityComparer comparer = new objAEqualityComparer();
List<objA> result =
name1
.IntersectIgnoreEmpty(name2, comparer)
.IntersectIgnoreEmpty(name3, comparer)
.IntersectIgnoreEmpty(name4, comparer)
.IntersectIgnoreEmpty(name5, comparer)
.ToList();