LINQ选择具有不同类型的集合中的项目

时间:2012-04-06 01:04:15

标签: c# linq

如何实现LINQ从类型A的一个对象集合中提取Guid,以便它们可以从另一个类型为B的对象集合中排除这些Guid。对象A和对象B都有一个名为“ID”的Guid字段。 “

我有以下内容:

  1. ObservableCollection<Component> component组件有一个 类型为ID
  2. Guid字段
  3. ObservableCollection<ComponentInformation> ComponentInformationCollection ComponentInformation 有一个名为ID Guid
  4. 的字段

    我的实施:

    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模式),因此上面的解决方案最适合我的情况。

5 个答案:

答案 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; }
    }