代码之家  ›  专栏  ›  技术社区  ›  Lasse V. Karlsen

在.NET4.0中有序列运算符实现吗?

  •  2
  • Lasse V. Karlsen  · 技术社区  · 15 年前

    我的意思是类似于linqjoin、group、distinct等,只处理值序列,而不是集合。

    我举个例子:

    var c1 = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
    var c2 = FunctionThatYieldsFibonacciNumbers();
    
    var c3 = c1.Except(c2);
    

    假设上面的函数只是一个While循环,除非显式停止枚举,否则不会终止,那么上面的代码将失败并出现内存不足异常。

    但是,考虑到我的集合被认为是严格升序或降序的,.NET 4.0中有没有实现可以:

    1. 给我所有共同的值(内部连接)
    2. 给我两者的所有值(并集/外连接)
    3. 给我序列1中所有不在序列2中的值

    c1 = the 1st and 15th of every month from january 2010 and onwards
    c2 = weekdays from 2010 and onwards
    c3 = all days in 2010-2012
    c4 = c1 and c2 and c3
    

    这将基本上给我在2010年到2012年每个月的1号和15号,但只有当这些日期在工作日。

    有了这些函数,就可以更容易地生成有问题的值,而不必显式地用它们构建集合。在上面的示例中,构建前两个集合需要知道第三个集合的约束,并且示例可能比上面的要复杂得多。

    2 回复  |  直到 15 年前
        1
  •  2
  •   Jon Skeet    15 年前

    我想说LINQ操作符已经在一般序列上工作了——但是它们不是专门为单调序列设计的,这就是你在这里看到的。

    我想写这样的东西并不难,但我不相信任何东西是内在的;据我所知,在系统中甚至没有任何关于这个场景的东西。

        2
  •  1
  •   Abel    15 年前

    你可以考虑一下 Seq module of F# ,通过使用特殊的F语言结构(如 1 .. 10 生成一个序列。它支持 infinite sequences 你描述的方式,因为它允许懒惰的评估。在你的情况下,使用F#可能是琐碎的,也可能不是琐碎的。但是,直接从C#使用Seq模块应该不会太难(但我自己没有尝试过)。

    跟随 this Mandelbrot example 显示了一种通过隐藏将无限序列与C#一起使用的方法 yield . 不确定它是否能让你更接近你想要的,但它可能会有所帮助。

    编辑
    虽然你已经评论说这在你当前的项目中是不值得的,并且接受了你问题的答案,但我对这个想法很感兴趣,并想出了一个小例子。

    它看起来相当琐碎,通过简单地包括FSharp.Core.dll,在C#以及.NET3.5和.NET4.0中运行良好( download it for .NET 3.5 )你的推荐人。下面是实现第一个用例的无限序列的开箱即用示例:

    // place in your using-section:
    using Microsoft.FSharp.Collections;
    using Microsoft.FSharp.Core;
    
    // [...]
    
    // trivial 1st and 15th of the month filter, starting Jan 1, 2010.
    Func<int, DateTime> firstAndFifteenth = (int i) =>
    {
        int year = i / 24 + 2010;
        int day = i % 2 != 0 ? 15 : 1;
        int month = ((int)i / 2) % 12 + 1;
        return new DateTime(year, month, day);
    };
    
    // convert func to keep F# happy
    var fsharpFunc = FSharpFunc<int, DateTime>.FromConverter(
                       new Converter<int, DateTime>(firstAndFifteenth));
    
    // infinite sequence, returns IEnumerable
    var infSeq = SeqModule.InitializeInfinite<DateTime>(fsharpFunc);
    
    // first 100 dates
    foreach (var dt in infSeq.Take(100))
        Debug.WriteLine("Date is now: {0:MM-dd-yyy}", dt);
    

    输出是可以预期的,前几行是这样的:

    Date is now: 01-01-2010
    Date is now: 01-15-2010
    Date is now: 02-01-2010
    Date is now: 02-15-2010
    Date is now: 03-01-2010