使用Linq从集合中获取对象

时间:2013-06-05 13:05:29

标签: c# .net linq

我在C#中有一个具有一些属性的对象:

// Pseudo class
public class
{
    Id;
    To;
    From;
}

我在Collection中有很多类的实例。这看起来像这样:

object 1:
  Id: 1
  To: "PathA"
  From: "PathB"

object 2:
  Id: 2
  To: "PathB"
  From: "PathC"

object 3:
  Id: 3
  To: "PathC"
  From: "PathA"

现在我要做的是获取该集合中的所有项目,其中To的值未出现在任何对象的From中。这将导致以下结果:

object 1:
  Id: 1
  To: "PathA"
  From: "PathB"

object 2:
  Id: 2
  To: "PathB"
  From: "PathC"

因为Id: 3的最后一个对象在PathA属性中有From,该属性已存在于To属性的某个位置。

如何使用Linq查询执行此操作?

5 个答案:

答案 0 :(得分:2)

嗯,怎么解决这个问题?首先,您可以创建To的所有值的索引。然后,根据From属性...

过滤您的序列

类似的东西:

var tos = new HashSet<string>(collection.Select(item => item.To));
var filtered = collection.Where(item => !tos.Contains(item.From));

您可能想要检查一下,如果创建HashSet确实是这样的,或者您需要以不同的方式构建它......但您明白了。如果tos变得相当长,那么集合是有效的,因为你会经常检查这个...

答案 1 :(得分:1)

说出你的对象集合如下:

var objects = { object1, object2, object3 }

然后你想要:

var result = objects.Where(o => !objects.Select(x => x.From).Contains(o.To));

如果它涉及大型数据集,则缓存并存储“从”路径的子选择可能是明智的:

var fromPaths = new HashSet<string>(objects.Select(x => x.From));
var result = objects.Where(o => !fromPaths.Contains(o.To))

答案 2 :(得分:1)

首先,您的示例与问题文本不匹配,因为所有示例对象的To都与其他From对应。但假设问题文本是正确的,样本是错误的:

使用group-join

怎么样?
var query = from obj in collection
            join fromObj in collection
                 on obj.To equals fromObj.From
                 into objGroup
            where !objGroup.Any()
            select obj;

或者,首先建立一组不同的Froms:

var distinctFroms = new HashSet<string>(collection.Select(item => item.From));

var query = from obj in collection
            where !distinctFroms.Contains(obj.To)
            select obj;

答案 3 :(得分:0)

var list = collection.Select(c=>c.To).Distinct().ToList();
var result = collection.Where(c=>!list.Contains(c.From)).ToList();

答案 4 :(得分:0)

如果您使用“收件人”和“收件人”作为相应的密钥将集合重新加入自身,则可以通过“收件人/来自”来确定哪些商品已“加入”并将其排除在外:

var itemsThatAreConnected = 
    collection.Join(collection, x => x.To, x => x.From, (a,b) => a);
var unconnected = collection.Except(itemsThatAreConnected);