Модуль F # Seq реализован в C # для IEnumerable? - PullRequest
11 голосов
/ 04 января 2009

F # имеет набор стандартных операторов последовательности, которые я знаю и люблю из своего опыта работы с Mathematica. Сейчас F # привлекает мое внимание, и когда он выйдет в общем выпуске, я собираюсь использовать его часто.

Прямо сейчас, поскольку F # еще не выпущен, я не могу использовать его в производственном коде. LINQ реализует некоторые из этих операторов, используя SQL-подобные имена (например, «select» - это «map», а «where» - «filter»), но я не могу найти реализации «fold», «iter» или «partition».

Кто-нибудь видел реализацию C # стандартных операторов последовательности? Это кто-то должен написать?

Ответы [ 6 ]

14 голосов
/ 19 января 2009

Если вы посмотрите внимательно, многие операции 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();
}

Элемент 0 содержит истинные значения; 1 содержит ложные значения. GroupBy - это, по сути, раздел по стероидам.

И, наконец, Seq.iter и Seq.iteri легко отображать:

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);
}
6 голосов
/ 04 января 2009
  • fold = 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;
        }
    }
}
1 голос
/ 17 июня 2009

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];
1 голос
/ 04 января 2009

iter существует как метод в классе List, который ForEach

в противном случае:

public static void iter<T>(this IEnumerable<T> source, Action<T> act) 
        {
            foreach (var item in source)
            {
                act(item);                
            }
        }
0 голосов
/ 19 января 2012

Вот обновление для решения dahlbyk partition.

Возвращено значение array[], где «элемент 0 содержит истинные значения; 1 содержит ложные значения» & mdash; но это не имеет места, когда все элементы совпадают или все не соответствуют предикату, и в этом случае у вас есть одноэлементный массив и мир боли.

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);
}
0 голосов
/ 05 января 2009

Раскатать свои собственные в C # - интересное упражнение, вот несколько моих. (См. Также здесь )

Обратите внимание, что iter / foreach в IEnumerable немного противоречив - я думаю, потому что вам нужно «завершить» (или как там это слово) 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);
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...