我为你做了两种扩展方法。
第一个将搜索以测试是否有一个项目在树中。
注意:您无法从列表中删除的原因是因为它在被枚举时无法更改。这是收藏的安全性。答案是复制列表或集合。我在我提供的删除代码示例中使用ToList() 完成了这项工作。请注意,我不需要在搜索版本中这样做,因为没有更改。
您提供搜索方式。
您提供访问嵌套类型的方法。
这是在树中搜索项目的示例:
var isInTree = dataList.FoundInTree(searchItem: item => item.Id == 6,
nestedItems: item => item.NestedData);
以下是从树中删除项目的示例:
var removedFromTree = dataList.RemoveFirstFromTree(searchItem: item => item.Id == 6,
nestedItems: item => item.NestedData);
我已经包含了这些方法的重载/变体,以允许搜索/删除相同的多个项目:
var isInTree = dataList.FoundInTree(searchItem: item => item.Id == 6,
nestedItems: item => item.NestedData,
out int foundCount);
var removedFromTree = dataList.RemoveAllFromTree(searchItem: item => item.Id == 6,
nestedItems: item => item.NestedData,
out int removedCount);
我还包含了一个示例应用程序,它模拟数据以显示如何使用它,但首先是扩展方法:
扩展方法(这是您的代码答案)
public static class Extensions
{
public static bool FoundInTree<T>(this IEnumerable<T> items, Func<T, bool> searchItem, Func<T, IEnumerable<T>> nestedItems)
{
foreach (var item in items)
{
if (searchItem.Invoke(item)) return true;
if (nestedItems.Invoke(item).FoundInTree(searchItem, nestedItems)) return true;
}
return false;
}
public static bool RemoveFirstFromTree<T>(this ICollection<T> items, Func<T, bool> searchItem, Func<T, ICollection<T>> nestedItems)
{
foreach (var item in items.ToList())
{
if (searchItem.Invoke(item))
{
items.Remove(item);
return true;
}
if (nestedItems.Invoke(item).RemoveFirstFromTree(searchItem, nestedItems))
{
return true;
}
}
return false;
}
public static bool FoundInTree<T>(this IEnumerable<T> items, Func<T, bool> searchItem, Func<T, IEnumerable<T>> nestedItems, out int count)
{
count = 0;
foreach (var item in items)
{
if (searchItem.Invoke(item)) count++;
if (nestedItems.Invoke(item).FoundInTree(searchItem, nestedItems, out int nestedCount)) count += nestedCount;
}
return count > 0;
}
public static bool RemoveAllFromTree<T>(this ICollection<T> items, Func<T, bool> searchItem, Func<T, ICollection<T>> nestedItems, out int count)
{
var isAnyRemoved = false;
count = 0;
foreach (var item in items.ToList())
{
if (searchItem.Invoke(item))
{
items.Remove(item);
isAnyRemoved = true;
count++;
}
if (nestedItems.Invoke(item).RemoveAllFromTree(searchItem, nestedItems, out int nestedCount))
{
isAnyRemoved = true;
count += nestedCount;
}
}
return isAnyRemoved;
}
}
现在这是完整的控制台应用程序(包括扩展方法)。您可以按原样复制和粘贴它,然后随意使用它。
控制台应用
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data;
using System.Linq;
using System.Net.Http.Headers;
using System.Text;
namespace Question_Answer_Console_App
{
class Program
{
static void Main(string[] args)
{
var dataList = GetMockData();
var isInTree = dataList.FoundInTree(searchItem: item => item.Id == 6,
nestedItems: item => item.NestedData,
out int foundCount);
if (isInTree)
{
Console.WriteLine($"Found {foundCount} items in the tree.");
}
else
{
Console.WriteLine("None found in the tree.");
}
var removedFromTree = dataList.RemoveAllFromTree(searchItem: item => item.Id == 6,
nestedItems: item => item.NestedData,
out int removedCount);
if (removedFromTree)
{
Console.WriteLine($"Removed {removedCount} items from the tree.");
}
else
{
Console.WriteLine($"No items removed from the tree.");
}
isInTree = dataList.FoundInTree(searchItem: item => item.Id == 6,
nestedItems: (item) => item.NestedData);
if (isInTree)
{
Console.WriteLine($"Found {foundCount} items in the tree.");
}
else
{
Console.WriteLine("None found in the tree.");
}
Console.ReadKey();
}
private static List<Data<int>> GetMockData()
{
var dataList = new List<Data<int>>();
for (var i = 0; i < 7; i++)
{
dataList.Add(getData(i));
}
return dataList;
Data<int> getData(int count)
{
var data = new Data<int>
{
Id = count
};
for (var j = count; j > 0; j--)
{
var innerData = new Data<int>
{
Id = j
};
innerData.NestedData.Add(getData(--j));
data.NestedData.Add(innerData);
}
return data;
}
}
}
public class Data<T>
{
public T Id { get; set; }
public List<Data<T>> NestedData { get; set; } = new List<Data<T>>();
}
public static class Extensions
{
public static bool FoundInTree<T>(this IEnumerable<T> items, Func<T, bool> searchItem, Func<T, IEnumerable<T>> nestedItems)
{
foreach (var item in items)
{
if (searchItem.Invoke(item)) return true;
if (nestedItems.Invoke(item).FoundInTree(searchItem, nestedItems)) return true;
}
return false;
}
public static bool RemoveFirstFromTree<T>(this ICollection<T> items, Func<T, bool> searchItem, Func<T, ICollection<T>> nestedItems)
{
foreach (var item in items.ToList())
{
if (searchItem.Invoke(item))
{
items.Remove(item);
return true;
}
if (nestedItems.Invoke(item).RemoveFirstFromTree(searchItem, nestedItems))
{
return true;
}
}
return false;
}
public static bool FoundInTree<T>(this IEnumerable<T> items, Func<T, bool> searchItem, Func<T, IEnumerable<T>> nestedItems, out int count)
{
count = 0;
foreach (var item in items)
{
if (searchItem.Invoke(item)) count++;
if (nestedItems.Invoke(item).FoundInTree(searchItem, nestedItems, out int nestedCount)) count += nestedCount;
}
return count > 0;
}
public static bool RemoveAllFromTree<T>(this ICollection<T> items, Func<T, bool> searchItem, Func<T, ICollection<T>> nestedItems, out int count)
{
var isAnyRemoved = false;
count = 0;
foreach (var item in items.ToList())
{
if (searchItem.Invoke(item))
{
items.Remove(item);
isAnyRemoved = true;
count++;
}
if (nestedItems.Invoke(item).RemoveAllFromTree(searchItem, nestedItems, out int nestedCount))
{
isAnyRemoved = true;
count += nestedCount;
}
}
return isAnyRemoved;
}
}
}
//OUTPUTS
//Found 2 items in the tree.
//Removed 2 items from the tree.
//None found in the tree.