用于IEnumerable的C#实现的F#Seq模块?

Gre*_*erg 11 c# f#

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 定义如下:

分裂成收集两个集合,包含用于所述给定谓词返回元件truefalse分别

我们可以使用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.iterSeq.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)


Mar*_*ell 6

  • fold = Aggregate

告诉我们做什么iterpartition做什么,我们可以填补空白.我猜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)