C# 如何正确实现IEnumerable以返回按属性排序的项?
我的目标是从匹配C# 如何正确实现IEnumerable以返回按属性排序的项?,c#,.net-core,ienumerable,C#,.net Core,Ienumerable,我的目标是从匹配Booenum条件的Foo列表中返回第一个Foo项,并且应该按照Boo值对其进行优先级排序,如示例所示,如果没有任何项匹配该条件,则只返回第一个项 模型: class Foo { E_Boo Boo { get; set; } } enum E_Boo { Undefined = 0, Jessie = 1, Abby = 2, Felix = 3, Lacey = 4, Lucia = 5, Anisa = 6
Boo
enum条件的Foo列表中返回第一个Foo
项,并且应该按照Boo
值对其进行优先级排序,如示例所示,如果没有任何项匹配该条件,则只返回第一个项
模型:
class Foo
{
E_Boo Boo { get; set; }
}
enum E_Boo
{
Undefined = 0,
Jessie = 1,
Abby = 2,
Felix = 3,
Lacey = 4,
Lucia = 5,
Anisa = 6
}
这就是我尝试的,它有效:
public Foo GetFooByBooPriority(IEnumerable<Foo> foos)
{
if(foos.Any(x => x.Boo == E_Boo.Abby))
return foos.First(x => x.Boo == E_Boo.Abby);
else if (foos.Any(x => x.Boo == E_Boo.Lacey))
return foos.First(x => x.Boo == E_Boo.Lacey);
else if (foos.Any(x => x.Boo == E_Boo.Lucia))
return foos.First(x => x.Boo == E_Boo.Lucia);
else if (foos.Any(x => x.Boo == E_Boo.Felix))
return foos.First(x => x.Boo == E_Boo.Felix);
else if (foos.Any(x => x.Boo == E_Boo.Anisa))
return foos.First(x => x.Boo == E_Boo.Anisa);
else if (foos.Any(x => x.Boo == E_Boo.Jessie))
return foos.First(x => x.Boo == E_Boo.Jessie);
else
return foos.First();
}
public Foo GetFooByBooPriority(IEnumerable foos)
{
if(foos.Any(x=>x.Boo==E_Boo.Abby))
返回foos.First(x=>x.Boo==E_Boo.Abby);
else if(foos.Any(x=>x.Boo==E_Boo.Lacey))
返回foos.First(x=>x.Boo==E_Boo.Lacey);
else if(foos.Any(x=>x.Boo==E_Boo.Lucia))
返回foos.First(x=>x.Boo==E_Boo.Lucia);
else if(foos.Any(x=>x.Boo==E_Boo.Felix))
返回foos.First(x=>x.Boo==E_Boo.Felix);
else if(foos.Any(x=>x.Boo==E_Boo.Anisa))
返回foos.First(x=>x.Boo==E_Boo.Anisa);
else if(foos.Any(x=>x.Boo==E_Boo.Jessie))
返回foos.First(x=>x.Boo==E_Boo.Jessie);
其他的
返回foos.First();
}
你知道如何在性能和更干净的代码方面改进这个优先检索器吗
更新:
在这种情况下,优先级逻辑需要与enumE_Boo
定义解耦,换句话说,如果enum定义将被更改,优先级逻辑应该保持smae
我想将实现与枚举值和名称分离
一个简单的解决方案是在代码中添加一个列表
,并按照所需的E_Boo
值的顺序填充它:
var booOrder = new List<E_Boo>
{
E_Boo.Abby,
E_Boo.Lacey,
E_Boo.Lucia,
E_Boo.Felix,
// ... And so on
};
foos.OrderBy(x=>x.Boo.FirstOrDefault()
?@vasily.sib看起来像foos.OrderBy(x=>x.Boo.ToString())
会更好地匹配OP的代码……如果优先级是完全随机的(与您的示例不同),那么针对每个枚举条目的一个具有优先级的属性是您最好的选择。向您展示了如何做到这一点。@ShaharShokrani您可以实现一个IComparer
并将其传递给OrderBy
,如下所示:foos.OrderBy(x=>x.Boo,eBooComparerInstance)。FirstOrDefault()
出于性能原因,您可以在列表上使用计数排序->(只要枚举值是线性的,或者使用每个枚举值只有一位的标志时),就可以使用枚举值作为Foo
->数组的索引位置,然后在遍历Ienumerable之后,只需遍历列表并返回第一个非空的值。这应该是O(n)而且比普通的(O(n*log(n))更好,实际上您可能不会使用IndexOf
(由于线性搜索)在实际代码中,但作为解释,它是完美的。@AlexeiLevenkov如果它的值数量足够小,足以容纳一个枚举,我不会期望使用的搜索算法会导致任何性能问题。在性能方面,我可能想在列表上尝试一个数组,但我真的认为在这种情况下它不应该有多大关系。谢谢你不过,您的反馈是:-)如果booOrder
确实变大了,那么使用字典查找比使用IndexOf
进行线性搜索要好。不过,现在可能不需要进行这种优化。@RoadRunner我完全同意-但如果枚举变得那么大,那么性能损失可能是您最不担心的:-)
var result = foos.OrderBy(f => booOrder.IndexOf(f.Boo)).First();