如何实现LINQ从类型A的一个对象集合中提取Guid,以便它们可以从另一个类型为B的对象集合中排除这些Guid。对象A和对象B都有一个名为“ID”的Guid字段。 “
我有以下内容:
ObservableCollection<Component> component
组件有一个
类型为ID
Guid
字段
ObservableCollection<ComponentInformation> ComponentInformationCollection
ComponentInformation
有一个名为ID
Guid
我的实施:
component =>
{
if (component != null)
{
var cancelledComponents = new List<ComponentInformation>();
foreach (Component comp in component)
{
cancelledComponents.Add(new ComponentInformation() { ID = comp.ID });
}
this.ComponentInformationCollection.Remove(cancelledComponents);
}
});
我相信有一个更优雅的解决方案,我一直在努力解决,但我遇到的问题是创建一个'新的ComponentInformation',这样类型不会给我一个错误。
======最终解决方案=======
var cancelledComponentIDs = new HashSet<Guid>(component.Select(x => x.ID));
this.ComponentInformationCollection.Remove(
this.ComponentInformationCollection.Where(x => cancelledComponentIDs.Contains(x.ID)).ToList());
谢谢你: 杰森 - 我用它作为我最终解决方案的模板(如下所列)。 Servy - 虽然我可以使用比较器,但我认为对于这种特殊情况,由于其一次性使用的情况,比较器不是必需的。
ComponentInformationCollection是一个Silverlight DependencyProperty,它会在更改时触发INotifyChangedEvent(MVVM模式),因此上面的解决方案最适合我的情况。
答案 0 :(得分:4)
我会这样做:
var ids = new HashSet<Guid>(
component.Select(x => x.ID)
);
var keepers = ComponentInformationCollection.Where(x => !ids.Contains(x.ID));
答案 1 :(得分:1)
如果Component
尚未定义使用ID进行比较的Equals和GetHashCode,则可以定义比较器,如下所示:
class ComponentComparer : IEqualityComparer<Component>
{
public int Compare(Component a, Component b)
{
return a.ID.CompareTo(b.ID);
}
public int GetHashCode(Component a)
{
return a.ID.GetHashCode();
}
}
然后你可以使用:
var result = componentCollectionA.Except(componentCollectionB, new ComponentComparer());
(从我的头顶写下;可能需要稍作修改才能编译。)
答案 2 :(得分:1)
LINQ将允许您找到所需的GUID,但LINQ序列通常是不可变的;你仍然需要使用某种循环来实际更改集合。诀窍是获取要删除的原始集合的正确实例。
实现一个等式/比较接口是一种方法,如果你需要在多个地方比较对象的相等性,那么绝对是可行的方法。如果你不想这样做,这应该可以得到你想要的东西:
var removeme = (from x in this.ComponentInformationCollection
join y in component on x.ID equals y.ID
select x).ToList();
removeme.ForEach(x => this.ComponentInformationCollection.Remove(x));
答案 3 :(得分:0)
大声思考(意思是我没有创建项目和类型并编译它),但是如何:
var cancelledComponents = component.Select(c=> new ComponentInformation() {ID = c.ID}).ToList();
cancelledComponents.ForEach(c => ComponentInformationCollection.Remove(c));
答案 4 :(得分:0)
有很多方法可以解决这个问题...这是一个非常简单的Linq语句,可以从集合中查询您要查找的内容。
var keep = typeAList.Where(a => typeBList.FirstOrDefault(b => a.ID == b.ID) == null);
这是我放在一起演示它的小测试应用程序。
class Program
{
static void Main(string[] args)
{
List<TypeA> typeAList = new List<TypeA>();
typeAList.Add(new TypeA() { ID = Guid.NewGuid() });
typeAList.Add(new TypeA() { ID = Guid.NewGuid() });
typeAList.Add(new TypeA() { ID = Guid.NewGuid() });
List<TypeB> typeBList = new List<TypeB>();
typeBList.Add(new TypeB() { ID = typeAList[0].ID });
typeBList.Add(new TypeB() { ID = typeAList[1].ID });
//this is the statement
var keep = typeAList.Where(a => typeBList.FirstOrDefault(b => a.ID == b.ID) == null);
}
}
class TypeA
{
public Guid ID { get; set; }
}
class TypeB
{
public Guid ID { get; set; }
}