O'LinQ-fu大师,请帮忙.
我有一个要求,我必须使用VB.NET中的Target.AddRange()从IEnumerable(Of T)(让我们称之为Source)将项添加到List(Of T)(让我们称之为Target).
Target.AddRange(Source.TakeWhie(Function(X, Index) ?))
的?part是一个棘手的条件,例如:只要尚未列举的计数不等于将列表填充到所需的最小值,然后随机决定是否应该采用当前项目,否则采取该项目. Somethig喜欢......
Source.Count() - Index = _minimum_required - _curr_count_of_items_taken _ OrElse GetRandomNumberBetween1And100() <= _probability_this_item_is_taken ' _minimum_required and _probability_this_item_is_taken are constants
令人困惑的部分是每次满足TakeWhile语句时都需要递增_curr_count_of_items_taken.我该怎么做呢?
我也对使用任何其他LINQ方法(Aggregate,Where等)而不是TakeWhile的解决方案持开放态度.
如果所有其他方法都失败了,那么我将回到使用一个好的旧的for-loop =)
但希望有一个LINQ解决方案.在此先感谢您的任何建议.
编辑:请求的旧的for-loop版本:
Dim _source_total As Integer = Source.Count() For _index As Integer = 0 To _source_total - 1 If _source_total - _index = MinimumRows - Target.Count _ OrElse NumberGenerator.GetRandomNumberBetween1And100 <= _possibility_item_is_taken Then Target.Add(Source(_index)) End If Next
编辑:大卫的无副作用答案接近我需要的同时保持可读性.也许他是唯一一个能理解我传达不良的伪代码的人.事后看来,OrderBy(GetRandomNumber)非常出色.我只需要将Take(3)部分更改为Take(MinimumRequiredPlusAnOptionalRandomAmountExtra)并在结尾处删除OrderBy和Select.感谢其他人的建议.
基本上你需要引入副作用.
在C#中,这相对容易 - 您可以使用lambda表达式来更新捕获的变量.在VB中,这可能仍然存在,但我不想猜测语法.我不太了解你的情况(听起来有点倒退),但你可以这样做:
C#会是这样的:
int count = 0; var query = source.TakeWhile(x => count < minimumRequired || rng.Next(100) < probability) .Select(x => { count++; return x; }); target.AddRange(query);
每次实际拍摄物品时,计数都会增加.
请注意,我怀疑你真的想要Where
而不是TakeWhile
- 否则第一次rng
给出一个高数字,序列将结束.
编辑:如果你不能直接使用副作用,你可能会使用一个可怕的黑客.我没试过这个,但......
public static T Increment(ref int counter, T value) { counter++; return value; } ... int count = 0; var query = source.TakeWhile(x => count < minimumRequired || rng.Next(100) < probability) .Select(x => Increment(ref count, x)); target.AddRange(query);
换句话说,您将副作用放入单独的方法中,并使用计数器的pass-by-reference调用该方法.不知道它是否适用于VB,但可能值得一试.另一方面,循环可能更简单......
作为一种完全不同的接近它的方式,您的源是否已经是内存中的集合,您可以廉价地迭代它?如果是这样,只需使用:
var query = Enumerable.Concat(source.Take(minimumRequired), source.Skip(minimumRequired) .TakeWhile(condition));
换句话说,绝对抓住前n个元素,然后再次开始,跳过前n个元素并根据条件取其余元素.