c#和LINQ-根据对象的ID对对象进行分组,然后在其中查找公共值



我有一个对象集合,如下所示。

List<Product> productList=new List<Product>();

Product类的结构如下所示。

public class Product
{
public  int Id;
public Product(int id)
{
Id=id;
}
public List<SomeOtherList> t;
}

产品类包含一些其他列表

public class SomeOtherList 
{
private int value;
public  SomeOtherList(int val)
{
value=val;
}

}
Product prodOne=new Product(1);
List<SomeOtherList> temp_1=new List<SomeOtherList>();
temp_1.Add(new SomeOtherList(10));
temp_1.Add(new SomeOtherList(20));
temp_1.Add(new SomeOtherList(30));
prodOne.t=temp_1;
Product prodTwo=new Product(2);
List<SomeOtherList> temp_2=new List<SomeOtherList>();
temp_2.Add(new SomeOtherList(100));
temp_2.Add(new SomeOtherList(40));
temp_2.Add(new SomeOtherList(30));
prodTwo.t=temp_2;

Product prodThree=new Product(1);
List<SomeOtherList> temp_3=new List<SomeOtherList>();
temp_3.Add(new SomeOtherList(10));
temp_3.Add(new SomeOtherList(20));
prodThree.t=temp_3;

productList.Add(prodOne);
productList.Add(prodTwo);
productList.Add(prodThree);

我想获得所有产品通用的"SomeOtherList"对象。例如,对于ProductId 1,我应该获取SometherList对象20作为公共对象。

我已经编写了以下LINQ查询来实现这一点。

List<Product> t=productList
.GroupBy(p => p.Id)
.Where(g => g.Count() == productList.Count)
.Select(x => x.First())
.ToList();

但它并没有给我想要的。有人能指出这个查询出了什么问题吗?

当乘积为某个特定值(即1)时,您想要的是SomeOtherList之间的交集

因此,您需要首先选择每个具有正确IdProduct,然后将它们的SomeOtherList连接在一起并按值分组。

要做到这一点,我们需要Product的每个SomeOtherList进行平坦化,这可以用SelectMany来完成

将序列的每个元素投影到IEnumerable,并将生成的序列展平为一个序列。


单个Id

如果我们只对一个Id感兴趣,那么我们可以进行以下

var common1 = productList
.Where(product => product.Id == 1)
.SelectMany(product => product.t)
.GroupBy(groupValue => groupValue.value)
.Where(groupValue => groupValue.Count() > 1)
.Select(values => values.First());

这将:

  1. 根据Id等于1筛选产品
  2. 将每个产品SomeOtherList展平为一个IEnumerable
  3. 根据SomeOtherList.value对每个元素进行分组
  4. 筛选出任何只有1个条目的组,因为我们只想要那些常见的组

所有Id

然而,如果我们想获得每个密钥的所有重复项的列表,那么我们可以与单个Id相同,但第一步是根据Id进行分组。

var common = productList
.GroupBy(groupId => groupId.Id)
.Select(groupId => groupId.SelectMany(product => product.t)
.GroupBy(groupValue => groupValue.value)
.Where(groupValue => groupValue.Count() > 1)
.Select(values => values.First().value));

在单个LINQ查询中很难做到,但以下代码应该可以工作。

var min = productList.Min(x=>x.Id);
var max = productList.Max(x=>x.Id);
for(int i = min; i<=max;i++)
{
var products = productList.Where(x=>x.Id = i).ToList();
List<SomeOtherList> cList = new List<SomeOtherList>();
foreach(var product in products)
{
cList.AddRange(product.t);
}
var distinctList = cList.Distinct();
}

由于嵌套列表,在再次分组之前,您需要使用SelectMany对SomeOtherList的列表进行分组打开包装。我认为这就是你想要的。

var result = productList
.GroupBy(p => p.Id)
.Select(pg =>
new
{
Id = pg.Key,
CommonOtherList = pg
.SelectMany(solg => solg.t)
.GroupBy(solg => solg.value)
.Where(solg => solg.Count() == pg.Count())
.Select(solg => new { OtherId = solg.Key })
});
foreach (var product in result)
{
Console.WriteLine(product.Id);
Console.WriteLine("**Common**");
foreach (var otherProduct in product.CommonOtherList)
{
Console.WriteLine("-->{0}", otherProduct.OtherId);
}
}

相关内容

最新更新