如果我有类似IEnumerable的内容:
string[] items = new string[] { "a", "b", "c", "d" };
我想遍历所有成对的连续项(大小为2的滑动窗口).会是
("a","b"), ("b", "c"), ("c", "d")
我的解决方案是这个
public static IEnumerable<Pair<T, T>> Pairs(IEnumerable<T> enumerable) {
IEnumerator<T> e = enumerable.GetEnumerator(); e.MoveNext();
T current = e.Current;
while ( e.MoveNext() ) {
T next = e.Current;
yield return new Pair<T, T>(current, next);
current = next;
}
}
// used like this :
foreach (Pair<String,String> pair in IterTools<String>.Pairs(items)) {
System.Out.PrintLine("{0}, {1}", pair.First, pair.Second)
}
当我编写此代码时,我想知道.NET框架中是否已经存在可以执行相同操作的函数,并且该函数不仅针对成对,而且针对任何大小的元组。 恕我直言,应该有一种很好的方法来执行这种滑动窗口操作。
我使用C#2.0,我可以想象使用C#3.0(带有LINQ)有更多(更好的方法)来做到这一点,但是我主要对C#2.0解决方案感兴趣.但是,我也会欣赏C#3.0解决方案。
最新回答
- 2021-1-111 #
- 2021-1-112 #
而不是要求元组(对)类型,为什么不只接受选择器:
public static IEnumerable<TResult> Pairwise<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TSource, TResult> resultSelector) { TSource previous = default(TSource); using (var it = source.GetEnumerator()) { if (it.MoveNext()) previous = it.Current; while (it.MoveNext()) yield return resultSelector(previous, previous = it.Current); } }
如果需要,可以让您跳过中间对象:
string[] items = new string[] { "a", "b", "c", "d" }; var pairs = items.Pairwise((x, y) => string.Format("{0},{1}", x, y)); foreach(var pair in pairs) Console.WriteLine(pair);
或者您可以使用匿名类型:
var pairs = items.Pairwise((x, y) => new { First = x, Second = y });
- 2021-1-113 #
最简单的方法是使用ReactiveExtensions
using System.Reactive; using System.Reactive.Linq;
并使自己成为将工具一起打击的扩展方法
public static IEnumerable<IList<T>> Buffer<T>(this IEnumerable<T> seq, int bufferSize, int stepSize) { return seq.ToObservable().Buffer(bufferSize, stepSize).ToEnumerable(); }
- 2021-1-114 #
晚了一点,但是作为所有这些扩展方法的替代方法,可以使用实际的"滑动"
Collection
来保存(并丢弃)数据。这是我今天最后做的一个:
public class SlidingWindowCollection<T> : ICollection<T> { private int _windowSize; private Queue<T> _source; public SlidingWindowCollection(int windowSize) { _windowSize = windowSize; _source = new Queue<T>(windowSize); } public void Add(T item) { if (_source.Count == _windowSize) { _source.Dequeue(); } _source.Enqueue(item); } public void Clear() { _source.Clear(); } ...and just keep forwarding all other ICollection<T> methods to _source. }
用法:
int pairSize = 2; var slider = new SlidingWindowCollection<string>(pairSize); foreach(var item in items) { slider.Add(item); Console.WriteLine(string.Join(", ", slider)); }
- 2021-1-115 #
为方便起见,这里是@dahlbyk答案的无选择器版本。
public static IEnumerable<Tuple<T, T>> Pairwise<T>(this IEnumerable<T> enumerable) { var previous = default(T); using (var e = enumerable.GetEnumerator()) { if (e.MoveNext()) previous = e.Current; while (e.MoveNext()) yield return Tuple.Create(previous, previous = e.Current); } }
相关问题
- c#:获取windows 8自动颜色主题的活动颜色c#netwpfwinapiwindows82021-01-12 01:28
- c#:遍历函数结果时,foreach如何工作?c#netforeach2021-01-11 17:26
- c#:并行执行任务c#netasynchronousasyncawaittaskparallellibrary2021-01-11 04:56
- c#:静态和实例方法同名?c#netoop2021-01-11 05:55
- c#:RequestUrlReferrer为空?c#netvisualstudiovisualstudio20082021-01-11 07:24
在.NET 4中,这变得更加容易:-