F#有一堆标准的序列操作符,我已经了解并喜欢我对Mathematica的体验.F#现在得到了很多关注,当它一般发布时,我打算经常使用它.
现在,由于F#尚未普遍发布,我无法在生产代码中真正使用它.LINQ使用类似SQL的名称来实现其中一些运算符(例如'select'是'map','where'是'filter'),但是我找不到'fold','iter'或'partition'的实现.
有没有人见过标准序列运算符的任何C#实现?这是某人应该写的东西吗?
dah*_*byk 15
如果仔细观察,许多Seq操作都具有LINQ等效或可以轻松派生.只是看下面的清单 ......
Seq.append = Concat<TSource>(IEnumerable<TSource> second)
Seq.concat = SelectMany<IEnumerable<TSource>, TResult>(s => s)
Seq.distinct_by = GroupBy(keySelector).Select(g => g.First())
Seq.exists = Any<TSource>(Func<TSource, bool> predicate)
Seq.mapi = Select<TSource, TResult>(Func<TSource, Int32, TResult> selector)
Seq.fold = Aggregate<TSource, TAccumulate>(TAccumulate seed, Func<TAccumulate, TSource, TAccumulate> func)
List.partition 定义如下:
分裂成收集两个集合,包含用于所述给定谓词返回元件
true和false分别
我们可以使用GroupBy和一个双元素数组作为穷人的元组来实现:
public static IEnumerable<TSource>[] Partition<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
return source.GroupBy(predicate).OrderByDescending(g => g.Key).ToArray();
}
Run Code Online (Sandbox Code Playgroud)
元素0保存真实值; 1保存虚假值.GroupBy基本上是类固醇的分区.
最后,Seq.iter并Seq.iteri容易映射到的foreach:
public static void Iter<TSource>(this IEnumerable<TSource> source, Action<TSource> action)
{
foreach (var item in source)
action(item);
}
public static void IterI<TSource>(this IEnumerable<TSource> source, Action<Int32, TSource> action)
{
int i = 0;
foreach (var item in source)
action(i++, item);
}
Run Code Online (Sandbox Code Playgroud)
Aggregate告诉我们做什么iter和partition做什么,我们可以填补空白.我猜iter = SelectMany和分区可能涉及Skip/ Take?
(更新)我查找了分区 - 这是一个粗略的实现,它做了一些:
using System;
using System.Collections.Generic;
static class Program { // formatted for space
// usage
static void Main() {
int[] data = { 1, 2, 3, 4, 5, 6 };
var qry = data.Partition(2);
foreach (var grp in qry) {
Console.WriteLine("---");
foreach (var item in grp) {
Console.WriteLine(item);
}
}
}
static IEnumerable<IEnumerable<T>> Partition<T>(
this IEnumerable<T> source, int size) {
int count = 0;
T[] group = null; // use arrays as buffer
foreach (T item in source) {
if (group == null) group = new T[size];
group[count++] = item;
if (count == size) {
yield return group;
group = null;
count = 0;
}
}
if (count > 0) {
Array.Resize(ref group, count);
yield return group;
}
}
}
Run Code Online (Sandbox Code Playgroud)