我有一个类,像这样:
public class MyClass
{
public int Value { get; set; }
public bool IsValid { get; set; }
}
实际上它要大得多,但这会重现问题(奇怪)。
我想得到 Value 的总和,其中实例有效。到目前为止,我已经找到了两种解决方案。
int result = myCollection.Where(mc => mc.IsValid).Select(mc => mc.Value).Sum();
int result = myCollection.Select(mc => mc.IsValid ? mc.Value : 0).Sum();
我想获得最有效的方法。起初,我认为第二个会更有效率。然后我的理论部分开始“好吧,一个是 O(n + m + m),另一个是 O(n + n)。第一个应该在更多无效的情况下表现更好,而第二个应该表现更好用更少”。我以为他们会表现得一样。 编辑:然后@Martin 指出 Where 和 Select 结合在一起,所以它实际上应该是 O(m + n)。但是,如果您往下看,这似乎与此无关。
(超过 100 行,所以我认为最好将其作为 Gist 发布。)
结果……很有趣。
天平有利于 Select和 Where , 大约 30 点。
How much do you want to be the disambiguation percentage?<br/>
0<br/>
Starting benchmarking.<br/>
Ties: 0<br/>
Where + Select: 65<br/>
Select: 36<br/>
除了一些误差在 2% 以内外,两者都是一样的。我会说这是最小误差范围。 Select和 Where现在只有大约 20 分的领先优势。
How much do you want to be the disambiguation percentage?<br/>
2<br/>
Starting benchmarking.<br/>
Ties: 6<br/>
Where + Select: 58<br/>
Select: 37<br/>
这就是我所说的最大误差范围。它使 Select 变得更好一点, 但不多。
How much do you want to be the disambiguation percentage?<br/>
5<br/>
Starting benchmarking.<br/>
Ties: 17<br/>
Where + Select: 53<br/>
Select: 31<br/>
这超出了我的误差范围,但我仍然对结果感兴趣。因为它给出了 Select和 Where它已经有一段时间领先 20 分了。
How much do you want to be the disambiguation percentage?<br/>
10<br/>
Starting benchmarking.<br/>
Ties: 36<br/>
Where + Select: 44<br/>
Select: 21<br/>
这超出了我的误差范围,方式,但我仍然对结果感兴趣,因为 Select和 Where 仍然(几乎)保持他们 20 分的领先优势。它似乎在少数几个方面超越了它,这就是它领先的原因。
How much do you want to be the disambiguation percentage?<br/>
25<br/>
Starting benchmarking.<br/>
Ties: 85<br/>
Where + Select: 16<br/>
Select: 0<br/>
现在,我猜测 20 分的领先优势来自中间位置,他们肯定会在附近获得相同的表现。我可以尝试记录它,但要吸收大量信息。我想图表会更好。
这就是我所做的。
它表明 Select线保持稳定(预期)并且 Select + Where线路攀升(预期)。然而,令我困惑的是为什么它不符合 Select在 50 或更早:事实上我期望早于 50,因为必须为 Select 创建一个额外的枚举器和 Where .我的意思是,这显示了 20 分的领先优势,但并没有解释原因。我想这就是我的问题的要点。
正如@KingKong 在评论中提到的,您还可以使用 Sum需要 lambda 的重载。所以我的两个选项现在变成了这样:
int result = myCollection.Where(mc => mc.IsValid).Sum(mc => mc.Value);
int result = myCollection.Sum(mc => mc.IsValid ? mc.Value : 0);
我打算让它更短一些,但是:
How much do you want to be the disambiguation percentage?<br/>
0<br/>
Starting benchmarking.<br/>
Ties: 0<br/>
Where: 60<br/>
Sum: 41<br/>
How much do you want to be the disambiguation percentage?<br/>
2<br/>
Starting benchmarking.<br/>
Ties: 8<br/>
Where: 55<br/>
Sum: 38<br/>
How much do you want to be the disambiguation percentage?<br/>
5<br/>
Starting benchmarking.<br/>
Ties: 21<br/>
Where: 49<br/>
Sum: 31<br/>
How much do you want to be the disambiguation percentage?<br/>
10<br/>
Starting benchmarking.<br/>
Ties: 39<br/>
Where: 41<br/>
Sum: 21<br/>
How much do you want to be the disambiguation percentage?<br/>
25<br/>
Starting benchmarking.<br/>
Ties: 85<br/>
Where: 16<br/>
Sum: 0<br/>
20 分的领先优势仍然存在,这意味着它与 Where 无关和 Select @Marcin 在评论中指出的组合。
感谢您阅读我的文字墙!另外,如果您有兴趣,here's记录 Excel 接收的 CSV 的修改版本。
最佳答案
Select 在整个集合上迭代一次,并为每个项目执行条件分支(检查有效性)和 + 操作。
Where+Select 创建一个跳过无效元素的迭代器(不会 yield 它们),仅对有效元素执行 + .
因此,Select 的成本是:
t(s) = n * ( cost(check valid) + cost(+) )
对于Where+Select:
t(ws) = n * ( cost(check valid) + p(valid) * (cost(yield) + cost(+)) )
地点:
p(valid) 是列表中某项有效的概率。cost(check valid)是检查有效性的分支的成本cost(yield) 是where 迭代器构造新状态的代价,它比Select版本使用。如您所见,对于给定的 n,Select 版本是常数,而 Where+Select 版本是线性的以 p(valid) 作为变量的等式。成本的实际值决定了两条线的交点,由于 cost(yield) 可以不同于 cost(+),因此它们不一定相交在 p(有效)=0.5。
关于c# - 为什么 Where 和 Select 的表现优于 Select?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18331774/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返
它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput
我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串
如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象
关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?
关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion在首页我有:汽车:VolvoSaabMercedesAudistatic_pages_spec.rb中的测试代码:it"shouldhavetherightselect"dovisithome_pathit{shouldhave_select('cars',:options=>['volvo','saab','mercedes','audi'])}end响应是rspec./spec/request