这是我的产品型号
public class Product
{
public string Name{ get; set; }
public int ProductNumber{ get; set; }
public List<Product> ProductList { get; set; }
}
//// below is the structure of the list
IList<Product> rootList = new List<Product>
{
new Product
{
ProductNumber = 1, Name = "A",
ProductList = new List<Product> { new Product { ProductNumber = 2, Name = "A1",
ProductList = new List<Product> { new Product { ProductNumber = 3, Name = "A2", ProductList = new List<Product>()} }}
}
},
new Product
{
ProductNumber = 4, Name = "B",
ProductList = new List<Product> { new Product { ProductNumber = 5, Name = "B1",
ProductList = new List<Product> { new Product { ProductNumber = 6, Name = "B2", ProductList = new List<Product>()} }}
}
},
new Product
{
ProductNumber = 7, Name = "C",
ProductList = new List<Product> { new Product { ProductNumber = 8, Name = "C1",
ProductList = new List<Product> { new Product { ProductNumber = 9, Name = "C2", ProductList = new List<Product>()} }}
}
}
};
我需要过滤上面包含ProductNumber小于5的列表,即。输出预计是产品编号小于5的产品列表。
有可用的扩展吗?请帮忙。
这是我的预期结果
Product
{
ProductNumber : 1,
Name : "A",
ProductList : { {
ProductNumber : 2,
Name : "A1",
ProductList :{ {
ProductNumber = 3,
Name : "A2",
ProductList : null} }}
}
},
Product
{
ProductNumber : 4,
Name : "B"
ProductList : null
}
答案 0 :(得分:4)
很容易将这个&#34; flatten-this-tree&#34;类LINQ函数
public static IEnumerable<T> Flatten<T>(
this IEnumerable<T> source,
Func<T, IEnumerable<T>> childSelector)
{
HashSet<T> added = new HashSet<T>();
Queue<T> queue = new Queue<T>();
foreach(T t in source)
if (added.Add(t))
queue.Enqueue(t);
while (queue.Count > 0)
{
T current = queue.Dequeue();
yield return current;
if (current != null)
{
IEnumerable<T> children = childSelector(current);
if (children != null)
foreach(T t in childSelector(current))
if (added.Add(t))
queue.Enqueue(t);
}
}
}
然后可以在常规LINQ中使用,例如
var lessThanFive = rootList
.Flatten(p => p.ProductList)
.Where(p => p.ProductNumber < 5)
.ToList();
编辑:从您的编辑中我可以看到,这并不是您想要的。 (你不想要一个产品清单,你想要一个产品树......)我会把它留在这里,因为我非常喜欢它作为我思想的解决方案你的问题是,但我也会考虑你的新问题......
编辑:如果您不介意修改原始对象,可以按如下方式使用:
rootList = rootList.Where(p => p.ProductNumber < 5).ToList();
foreach (var pr in rootList.Flatten(p => p.ProductList))
pr.ProductList = pr.ProductList.Where(p => p.ProductNumber < 5).ToList();
答案 1 :(得分:0)
你需要这样的东西:
public static class EnumerableExtensions
{
public static IEnumerable<TR> Recur<T, TR>(
this IEnumerable<T> source,
Func<T, bool> filter,
Func<T, IEnumerable<T>> recursor,
Func<T, IEnumerable<T>, TR> resultor)
{
foreach(var t in source)
if (filter(t))
yield return resultor(t, recursor(t));
}
}
你会这样称呼:
var q = rootList.Recur(
p => p.ProductNumber < 5,
p => p.ProductList,
(p, cs) => new
{
p.ProductNumber,
p.Name,
ProductList = cs
});