有没有更简洁的方法来重用三元的bool测试中的结果作为三元的输出?
c#
假设我有一个集合,其中一些形状可能是蓝色的。如果有蓝色形状,我想返回蓝色形状的数量。如果没有蓝色形状,我想返回所有形状的计数。这是在初始化程序中完成的,而且蓝色形状的计数又长又丑:
new SomeObject {
CountOf = someCollection.Shapes.Count(s => s.Attributes.First(a => a.Name == "Color").Value == "Blue") > 0 ?
(someCollection.Shapes.Count(s => s.Attributes.First(a => a.Name == "Color").Value == "Blue") :
someCollection.Shapes.Count()
}
..这甚至更长,更丑陋,并且计数两次。可以通过将其设置为 Any 而不是 Count 来优化一些,但让我们假设我知道大部分时间接近末尾会有蓝色形状,因此循环 Any+Count 几乎与循环循环一样消耗资源算了,还是会丑
我可以像这样重复使用计数:
int c;
new SomeObject {
CountOf = (c = someCollection.Shapes.Count(s => s.Attributes.First(a => a.Name == "Color").Value == "Blue")) > 0 ?
c :
someCollection.Shapes.Count()
}
..this 依靠赋值c返回赋值的值,并对其进行 bool 测试,然后我们可以c在输出中使用。我不知道有一种方法可以声明c内联到三元。(它仍然可能计数两次)
不可能使用正在初始化的属性作为三元中的临时存储,也不可能将其初始化两次(尽管它可以初始化为蓝色的计数,然后在创建后进行测试并更改为 0)并且 C# 没有任何真实性行为像JavaScript可能会被利用来挑选b的a||b,如果a是0 ..
有没有什么技巧可以让我整理和优化这种形式的三元组,somevalue_test : somevalue : othervalue例如这个计数,或者甚至更简单的三元组,例如some.Long.Chain.To.A.String.Length > 100 ? some.Long.Chain.To.A.String.Remove(100) : some.Long.Chain.To.A.String?
定义:“整洁” - 单行,不[主要]重复代码,或一些truthy/falsy风格的替代品
回答
我要么只使用一个局部变量(这意味着它不能成为对象初始值设定项的一部分,但有时这只是事情的方式)或编写一个扩展方法:
// TODO: Rename!
public static int CountIfAnyOrAll<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
int totalCount = 0;
int matchingCount = 0;
foreach (var item in source)
{
totalCount++;
if (predicate(item))
{
matchingCount++;
}
}
return matchingCount == 0 ? totalCount : matchingCount;
}
请注意,这可确保您只对序列进行一次迭代,这在 evenCount()代价高昂的情况下很有用,或者如果多次迭代序列可能会给出不一致的结果。