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

C# F#Seq模块在C中实现#用于IEnumerable?,c#,f#,C#,F#,F#有一组标准序列运算符,我从Mathematica的经验中了解并喜爱它们。F#现在得到了我很多的关注,当它正式发布时,我打算经常使用它 现在,由于F#还没有正式发布,我无法在生产代码中真正使用它。LINQ使用类似SQL的名称实现其中一些运算符(例如,“select”是“map”,而“where”是“filter”),但我找不到“fold”、“iter”或“partition”的实现 有人见过标准序列运算符的C#实现吗?这是应该有人写的吗? 折叠=聚合 告诉我们使用iter和分区所做的事情,我

F#有一组标准序列运算符,我从Mathematica的经验中了解并喜爱它们。F#现在得到了我很多的关注,当它正式发布时,我打算经常使用它

现在,由于F#还没有正式发布,我无法在生产代码中真正使用它。LINQ使用类似SQL的名称实现其中一些运算符(例如,“select”是“map”,而“where”是“filter”),但我找不到“fold”、“iter”或“partition”的实现

有人见过标准序列运算符的C#实现吗?这是应该有人写的吗?

  • 折叠=
    聚合
告诉我们使用iter和分区所做的事情,我们可能会填补空白。我猜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;
        }
    }
}
使用系统;
使用System.Collections.Generic;
静态类程序{//格式化为空格
//用法
静态void Main(){
int[]数据={1,2,3,4,5,6};
var qry=数据分区(2);
foreach(qry中的var grp){
Console.WriteLine(“--”);
foreach(grp中的var项目){
控制台写入线(项目);
}
}
}
静态可数划分(
此IEnumerable源(整数大小){
整数计数=0;
T[]group=null;//使用数组作为缓冲区
foreach(源中的T项){
如果(group==null)group=newt[size];
组[计数++]=项目;
如果(计数==大小){
收益率-收益率组;
组=空;
计数=0;
}
}
如果(计数>0){
调整数组大小(参考组、计数);
收益率-收益率组;
}
}
}

iter作为一种方法存在于ForEach的List类中

否则:

public static void iter<T>(this IEnumerable<T> source, Action<T> act) 
        {
            foreach (var item in source)
            {
                act(item);                
            }
        }
publicstaticvoiditer(此IEnumerable源代码,ActionAct)
{
foreach(源中的var项)
{
法案(项目);
}
}
用C#滚动你自己的是一个有趣的练习,下面是我的一些。(另见)

请注意,关于IEnumerable的iter/foreach有点争议——我认为这是因为你必须“敲定”(或不管是什么词)IEnumerable才能真正发生任何事情

    //mimic fsharp map function (it's select in c#)
    public static IEnumerable<TResult> Map<T, TResult>(this IEnumerable<T> input, Func<T, TResult> func)
    {
        foreach (T val in input)
            yield return func(val);
    }

    //mimic fsharp mapi function (doens't exist in C#, I think)
    public static IEnumerable<TResult> MapI<T, TResult>(this IEnumerable<T> input, Func<int, T, TResult> func)
    {
        int i = 0;
        foreach (T val in input)
        {
            yield return func(i, val);
            i++;
        }
    }

    //mimic fsharp fold function (it's Aggregate in c#)
    public static TResult Fold<T, TResult>(this IEnumerable<T> input, Func<T, TResult, TResult> func, TResult seed)
    {
        TResult ret = seed;
        foreach (T val in input)
            ret = func(val, ret);
        return ret;
    }

    //mimic fsharp foldi function (doens't exist in C#, I think)
    public static TResult FoldI<T, TResult>(this IEnumerable<T> input, Func<int, T, TResult, TResult> func, TResult seed)
    {
        int i = 0;
        TResult ret = seed;
        foreach (T val in input)
        {
            ret = func(i, val, ret);
            i++;
        }
        return ret;
    }

    //mimic fsharp iter function
    public static void Iter<T>(this IEnumerable<T> input, Action<T> action)
    {
        input.ToList().ForEach(action);
    }
//模拟fsharp映射函数(在c#中选择)
公共静态IEnumerable映射(此IEnumerable输入,Func Func)
{
foreach(输入中的T val)
收益回报函数(val);
}
//模拟fsharp mapi函数(我认为C#中不存在)
公共静态IEnumerable MapI(此IEnumerable输入,Func Func)
{
int i=0;
foreach(输入中的T val)
{
收益回报函数(i,val);
i++;
}
}
//模拟fsharp fold函数(它在c#中聚合)
公共静态TResult折叠(此IEnumerable输入、Func Func、TResult种子)
{
TResult ret=种子;
foreach(输入中的T val)
ret=func(val,ret);
返回ret;
}
//模拟fsharp foldi函数(我认为C#中不存在)
公共静态TResult FoldI(此IEnumerable输入、Func Func、TResult种子)
{
int i=0;
TResult ret=种子;
foreach(输入中的T val)
{
ret=func(i,val,ret);
i++;
}
返回ret;
}
//模拟fsharp iter功能
公共静态无效Iter(此IEnumerable输入,动作)
{
input.ToList().ForEach(操作);
}

如果仔细观察,许多Seq操作都具有LINQ等价物,或者可以很容易地派生出来。只是往下看

  • Seq.append=Concat(IEnumerable秒)

  • Seq.concat=SelectMany(s=>s)

  • Seq.distinct\u by=GroupBy(keySelector)。选择(g=>g.First())

  • Seq.exists=Any(Func谓词)

  • Seq.mapi=Select(函数选择器)

  • Seq.fold=聚合(tacumulate seed,Func 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();
}

ToLookup可能更适合List.partition:

IEnumerable<T> sequence = SomeSequence();
ILookup<bool, T> lookup = sequence.ToLookup(x => SomeCondition(x));
IEnumerable<T> trueValues = lookup[true];
IEnumerable<T> falseValues = lookup[false];
IEnumerable sequence=SomeSequence();
ILookup lookup=sequence.ToLookup(x=>SomeCondition(x));
IEnumerable trueValues=查找[true];
IEnumerable falseValues=查找[false];
这里是对
分区
解决方案的更新

它返回了一个
数组[]
,其中“元素0保存真值;元素1保存假值”-但当所有元素都匹配谓词或所有元素都未通过谓词时,这并不成立,在这种情况下,您将得到一个单例数组和一个痛苦的世界

public static Tuple<IEnumerable<T>, IEnumerable<T>> Partition<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
    var partition = source.GroupBy(predicate);
    IEnumerable<T> matches = partition.FirstOrDefault(g => g.Key) ?? Enumerable.Empty<T>();
    IEnumerable<T> rejects = partition.FirstOrDefault(g => !g.Key) ?? Enumerable.Empty<T>();
    return Tuple.Create(matches, rejects);
}
公共静态元组分区(此IEnumerable源,Func谓词)
{
var partition=source.GroupBy(谓词);
IEnumerable matches=partition.FirstOrDefault(g=>g.Key)??Enumerable.Empty();
IEnumerable rejects=partition.FirstOrDefault(g=>!g.Key)??Enumerable.Empty();
返回Tuple.Create(匹配、拒绝);
}

Select的重载确实存在mapi等效项。此外,将枚举转换为列表似乎有点繁重,而不是执行普通的foreach循环并每次调用操作……我不知道选择重载,谢谢。我想ToList是我想到的第一件事……除了它不是懒惰。当所有元素匹配或
public static Tuple<IEnumerable<T>, IEnumerable<T>> Partition<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
    var partition = source.GroupBy(predicate);
    IEnumerable<T> matches = partition.FirstOrDefault(g => g.Key) ?? Enumerable.Empty<T>();
    IEnumerable<T> rejects = partition.FirstOrDefault(g => !g.Key) ?? Enumerable.Empty<T>();
    return Tuple.Create(matches, rejects);
}