1

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

我有以下内容:

  1. ObservableCollection<Component> component 组件有一个名为IDtype的字段Guid
  2. ObservableCollection<ComponentInformation> ComponentInformationCollectionComponentInformation 有一个名为IDtype的字段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());

谢谢:Jason - 我用这个作为我最终解决方案的模板(如下所列)。Servy - 虽然我可以使用比较器,但我认为对于这种特殊情况,比较器不是必需的,因为它是一次性使用类型的情况。

ComponentInformationCollection 是一个 Silverlight DependencyProperty,它会在更改时触发 INotifyChangedEvent(MVVM 模式),因此上述解决方案最适合我的情况。

4

5 回答 5

4

我会这样做:

var ids = new HashSet<Guid>(
              component.Select(x => x.ID)
          );
var keepers = ComponentInformationCollection.Where(x => !ids.Contains(x.ID));
于 2012-04-06T01:10:44.703 回答
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());

(写在我的头上;可能需要稍作修改才能编译。)

于 2012-04-06T01:39:32.930 回答
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));
于 2012-04-06T01:46:47.100 回答
0

大声思考(意味着我没有创建项目和类型并编译它),但是如何:

var cancelledComponents = component.Select(c=> new ComponentInformation() {ID = c.ID}).ToList();
cancelledComponents.ForEach(c => ComponentInformationCollection.Remove(c));
于 2012-04-06T01:27:06.383 回答
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; }
    }
于 2012-04-06T01:46:02.067 回答