C# 是否有基于不同条件从集合中获取元素/变量的最佳实践
或者,一般来说,如何在单通道中根据不同和复杂的条件从集合中筛选某些元素 假设我们有元素集合C# 是否有基于不同条件从集合中获取元素/变量的最佳实践,c#,linq,filter,collections,C#,Linq,Filter,Collections,或者,一般来说,如何在单通道中根据不同和复杂的条件从集合中筛选某些元素 假设我们有元素集合 var cats = new List<Cat>{ new Cat("Fluffy"), new Cat("Meowista"), new Cat("Scratchy")}; 三元op的所有选项都不易扩展,且相对容易出错,但都非常简短且不明确,它们还依赖于不返回/使用三元op的实际结果(使用discard“uu”或“is null”作为bool)。我认为使用Funcs字典的方法是实现自定义条
var cats = new List<Cat>{ new Cat("Fluffy"), new Cat("Meowista"), new Cat("Scratchy")};
三元op的所有选项都不易扩展,且相对容易出错,但都非常简短且不明确,它们还依赖于不返回/使用三元op的实际结果(使用discard“uu”或“is null”作为bool)。我认为使用Funcs字典的方法是实现自定义条件的一个很好的候选方法,只需将它们与变量一起烘焙即可
谢谢,期待您的解决方案!:) 我不确定Linq是否可以开箱即用,但如果您可以选择编写一次自定义扩展,那么从具有任意数量条件的集合中检索某些值以后可能会非常简洁 例如,您可以编写如下内容
var (redCat, blueCat) = cats.FindFirsts(
x => x.Name == redCatName,
x => x.Name == blueCatName);
如果引入FindFirsts()
扩展,如下所示:
public static class FindExtensions
{
public static T[] FindFirsts<T>(this IEnumerable<T> collection,
params Func<T, bool>[] conditions)
{
if (conditions.Length == 0)
return new T[] { };
var unmatchedConditions = conditions.Length;
var lookupWork = conditions
.Select(c => (
value: default(T),
found: false,
cond: c
))
.ToArray();
foreach (var item in collection)
{
for (var i = 0; i < lookupWork.Length; i++)
{
if (!lookupWork[i].found && lookupWork[i].cond(item))
{
lookupWork[i].found = true;
lookupWork[i].value = item;
unmatchedConditions--;
}
}
if (unmatchedConditions <= 0)
break;
}
return lookupWork.Select(x => x.value).ToArray();
}
}
公共静态类findex
{
公共静态T[]FindFirsts(此IEnumerable集合,
参数Func[]条件)
{
if(conditions.Length==0)
返回新的T[]{};
var unmatchedConditions=条件.Length;
var lookupWork=条件
.选择(c=>(
值:默认值(T),
发现:错,
条件:c
))
.ToArray();
foreach(集合中的var项)
{
for(var i=0;i
完整的演示可以在这里进行:
注意:为了解构结果数组(即使用
var(redCat,blueCat)=…
),您必须定义解构扩展。为此,我从中借用了一些代码。我不确定使用Linq开箱即用是否可行,但如果您可以选择编写一次自定义扩展,则从具有任意数量条件的集合中检索某些值以后可能会非常简洁
例如,您可以编写如下内容
var (redCat, blueCat) = cats.FindFirsts(
x => x.Name == redCatName,
x => x.Name == blueCatName);
如果引入FindFirsts()
扩展,如下所示:
public static class FindExtensions
{
public static T[] FindFirsts<T>(this IEnumerable<T> collection,
params Func<T, bool>[] conditions)
{
if (conditions.Length == 0)
return new T[] { };
var unmatchedConditions = conditions.Length;
var lookupWork = conditions
.Select(c => (
value: default(T),
found: false,
cond: c
))
.ToArray();
foreach (var item in collection)
{
for (var i = 0; i < lookupWork.Length; i++)
{
if (!lookupWork[i].found && lookupWork[i].cond(item))
{
lookupWork[i].found = true;
lookupWork[i].value = item;
unmatchedConditions--;
}
}
if (unmatchedConditions <= 0)
break;
}
return lookupWork.Select(x => x.value).ToArray();
}
}
公共静态类findex
{
公共静态T[]FindFirsts(此IEnumerable集合,
参数Func[]条件)
{
if(conditions.Length==0)
返回新的T[]{};
var unmatchedConditions=条件.Length;
var lookupWork=条件
.选择(c=>(
值:默认值(T),
发现:错,
条件:c
))
.ToArray();
foreach(集合中的var项)
{
for(var i=0;i
完整的演示可以在这里进行:
注意:为了解构结果数组(即使用
var(redCat,blueCat)=…
),您必须定义解构扩展。为此,我从中借用了一些代码。您的意思是像cats。其中(x=>x.Name==redCatName | | x.Name==blueCatName)?你认为什么是“好”的方法?你问一个单程,所以看起来你关心的是性能。另一方面,你需要一个可读的OneliNER。在我的经验中,这2个要求经常冲突。对于Onelier-Posits,重要的是要知道,例如,你可以使用的多行通用扩展方法。那么作为一条直线使用是可以接受的吗?@Magnetron,实际上不是,我更喜欢在不同的“命名变量”中使用它们正如您在MarchBoxing方法中所看到的,一般来说,它就像将集合反汇编回单独的集合elements@Knoop,是的,这些是相互冲突的,但正如您在我的不同方法中看到的,它们非常适合所要求的内容,但也许有人可以做得更好?我们也很欣赏通用扩展方法,但这样我们仍然可以必须在调用方的site@VladFomin我可以问一下为什么吗?就我所见,你不需要知道哪个是“红猫”,哪个是蓝猫,一旦你有了它们,你就可以比较并返回winner cat对象。一旦你有了它们,把它们分配给“命名变量”是很便宜的你的意思是像cats.Where(x=>x.Name==redCatName | | x.Name==blueCatName)?你认为什么是“好”的方法?你问一个单程,所以看起来你关心的是性能。另一方面,你需要一个可读的OneliNER。在我的经验中,这2个要求经常冲突。对于Onelier-Posits,重要的是要知道,例如,你可以使用的多行通用扩展方法。那么作为一条直线使用是可以接受的吗?@Magnetron,实际上不是,我更喜欢在不同的“命名变量”中使用它们正如您在MarchBoxing方法中所看到的,一般来说,它就像将集合反汇编回单独的集合elements@Knoop,是的,这些是相互冲突的,但正如您在我的不同方法中看到的,它们非常适合所要求的内容,但也许有人可以做得更好?我们也很欣赏通用扩展方法,但这样我们仍然可以必须在调用方的site@VladFomin我可以问为什么吗?就我所见,你不需要知道哪个是“红猫”,哪个是“红猫”