Linq困境

时间:2009-05-26 15:30:05

标签: c# linq

我无法有效地选择我需要显示的信息。希望其他人更好地了解如何解决这个问题。

鉴于以下数据结构,

public class Department
{
   public int ID { get; set; }
   public string Name { get; set; }
   public IList<Product> Products{ get; set; }
}

public class Product
{
   public int ID { get; set; }
   public string Name { get; set; }
}

并给出以下数据

Department1 = 
{
    Id=1,
    Name="D1",
    Products = {new Product{Id=1, Name="Item1"}, new Product{Id=2, Name="Item2"}
}

Department2 = 
{
    Id=2,
    Name="D2",
    Products = {new Product{Id=2, Name="Item2"}, new Product{Id=3, Name="Item3"}
}

如何选择“Item2”对于“D1”和“D2”都是通用的?

我尝试过使用交集查询,但似乎希望两个延迟查询执行计划相交,而不是两个IEnumerable列表或IList。

非常感谢任何帮助。

编辑:通过努力保持简单,我似乎并不十分精确。

我有一个部门列表,每个部门都包含一个产品列表。根据这些列表,如何根据特定条件选择其他产品列表。在这个例子中我的标准是我只想选择我所有部门中存在的产品。我只想要与所有元素相交的数据。

7 个答案:

答案 0 :(得分:1)

我的Intersect功能正常运行:

        Department department1 = new Department
        {
            Id = 1,
            Name = "D1",
            Products = new List<Product> () { new Product { Id = 1, Name = "Item1" }, new Product { Id = 2, Name = "Item2" } }
        };

        Department department2 = new Department
        {
            Id = 2,
            Name = "D2",
            Products = new List<Product>() { new Product { Id = 2, Name = "Item2" }, new Product { Id = 3, Name = "Item3" } }
        };

        IEnumerable<Product> products = department1.Products.Intersect(department2.Products, new ProductComparer());

        foreach (var p in products)
        {
            Console.WriteLine(p.Name);
        }

(适用编辑)

    public class ProductComparer : IEqualityComparer<Product>
    {
        public bool Equals(Product x, Product y)
        {
            return x.Name == y.Name && x.Id == y.Id;
        }

        public int GetHashCode(Product obj)
        {
            return obj.Id.GetHashCode() ^ obj.Name.GetHashCode();
        }
    }

答案 1 :(得分:1)

如果您想使用Linq,那么您可以展平Products集合并将每个集合与父部门对象相关联(因此您拥有(Product,Department)对的集合),然后在Product上重新分组。

var sharedItems = new[] { department1, department2 }
                .SelectMany(d => d.Products, (dep, prod) => new { Department = dep, Product = prod })
                .GroupBy(v => v.Product)
                .Where(group => group.Count() > 1);

此查询的结果是IGroupings的枚举,其中密钥是产品,并包含具有该产品的部门。

答案 2 :(得分:1)

// Get a list of all departments.
IEnumerable<Department> departments = GetAllDepartments();

// Get a list of all products.
var products = departments.SelectMany(d => d.Products).Distinct();

// Filter out all products that are not contained in all departments.
var filteredProducts = products.
    Where(p => departments.All(d => d.Products.Contains(p)));

如果合并两个查询,则会得到以下结果。

var filteredProducts = departments.
    SelectMany(d => d.Products).
    Distinct().
    Where(p => departments.All(d => d.Products.Contains(p)));

答案 3 :(得分:0)

也许我不完全理解这个问题,但这会有用吗?

var commonProducts = new List<Product>();

Department1.Products.ForEach(delegate(Product product)
{
    if (Department2.Products.Contains(product))
    {
        commonProducts.Add(product);
    }
});

答案 4 :(得分:0)

使用SelectMany生成产品/部门对的扁平列表(可能在匿名类中),然后使用GroupBy按产品名称分组(并处理同一部门中同一产品的多个实例)。

如果我以后有机会,会扩大。

答案 5 :(得分:0)

将每个部门投射到IEnumerable<Product>。 汇总产品列表 - 使用第一个作为起点,并在剩余列表中使用Intersect。

List<Product> commonProducts = departments
  .Select(d => d.Products.AsEnumerable() )
  .Aggregate( (soFar, nextList) => soFar
    .Intersect(nextList, productComparer) )
  .ToList()

你必须实现一个ProductComparer来绕过引用相等 - 如果Product是一个struct,你就不必这样做了。

答案 6 :(得分:-1)

LINQ查询语法更适合这些类型的查询:

var q = from p1 in Department1.Products
        join p2 in Department2.Products
        on p1.Id equals p2.Id
        select p1;

foreach (Product p in q) Console.WriteLine(p.Name);