Mapuj i zmniejszaj w .NET

Odpowiedzi:

298

Odpowiedniki Linq Map i Reduce: Jeśli masz szczęście, że masz linq, nie musisz pisać własnej mapy i redukować funkcji. C # 3.5 i Linq mają już to, choć pod różnymi nazwami.

  • Mapa to Select:

    Enumerable.Range(1, 10).Select(x => x + 2);
  • Zmniejsz to Aggregate:

    Enumerable.Range(1, 10).Aggregate(0, (acc, x) => acc + x);
  • Filtr to Where:

    Enumerable.Range(1, 10).Where(x => x % 2 == 0);

https://www.justinshield.com/2011/06/mapreduce-in-c/

Tony
źródło
1
Tłumaczenie jest poprawne, ale pomija kluczowy punkt. Krok tasowania w map redukuje jest krytyczny w map-reduku, ale nie pojawia się w nazwie, więc nie trzeba pisać dla niego żadnego kodu. Jest sterowany wyłącznie przez klucz wyodrębniany w kroku mapy. Odpowiedź Joela Martineza podkreśla, że ​​moim zdaniem lepiej.
xtofs
2
Link nie działa, poprawny link to: justinshield.com/2011/06/mapreduce-in-c
Alexandru-Dan Pop
12
Dlaczego oh dlaczego nie po prostu nazwać to Reducezamiast Aggregate... MS po prostu lubi drażnić programistów
John Henckel
13
@JohnHenckel, na pewno nie jestem autorytatywnym źródłem, ale jestem prawie pewien, że pochodzi z SQL. Uważam, że linq został pierwotnie kupiony jako sposób na ułatwienie interakcji z sql w C #. Kiedy nazywasz funkcje w tym świecie, agregacja zaczyna brzmieć bardziej znajomo niż „redukcja” w porównaniu z takimi funkcjami jak Wybierz i Grupuj według. Nie mówię, że to prawda, irytuje mnie to bez końca, ale wyobrażam sobie, że to jest tego powód.
Elliot Blackburn
18

Klasy problemów, które dobrze nadają się do rozwiązania w stylu mapreduce, to problemy agregacji. Wyodrębniania danych ze zbioru danych. W C # można by skorzystać z LINQ do programowania w tym stylu.

Z następującego artykułu: http://codecube.net/2009/02/mapreduce-in-c-using-linq/

metoda GroupBy działa jak mapa, natomiast metoda Select redukuje wyniki pośrednie do ostatecznej listy wyników.

var wordOccurrences = words
                .GroupBy(w => w)
                .Select(intermediate => new
                {
                    Word = intermediate.Key,
                    Frequency = intermediate.Sum(w => 1)
                })
                .Where(w => w.Frequency > 10)
                .OrderBy(w => w.Frequency);

W przypadku części dystrybuowanej możesz sprawdzić DryadLINQ: http://research.microsoft.com/en-us/projects/dryadlinq/default.aspx

Joel Martinez
źródło
3

Ponieważ nigdy nie mogę zapamiętać, że LINQ to nazywa Where, Selecti Aggregatezamiast Filter, Mapa Reducewięc stworzyłem kilka metod przedłużających można użyć:

IEnumerable<string> myStrings = new List<string>() { "1", "2", "3", "4", "5" };
IEnumerable<int> convertedToInts = myStrings.Map(s => int.Parse(s));
IEnumerable<int> filteredInts = convertedToInts.Filter(i => i <= 3); // Keep 1,2,3
int sumOfAllInts = filteredInts.Reduce((sum, i) => sum + i); // Sum up all ints
Assert.Equal(6, sumOfAllInts); // 1+2+3 is 6

Oto 3 metody (z https://github.com/cs-util-com/cscore/blob/master/CsCore/PlainNetClassLib/src/Plugins/CsCore/com/csutil/collections/IEnumerableExtensions.cs ):

public static IEnumerable<R> Map<T, R>(this IEnumerable<T> self, Func<T, R> selector) {
    return self.Select(selector);
}

public static T Reduce<T>(this IEnumerable<T> self, Func<T, T, T> func) {
    return self.Aggregate(func);
}

public static IEnumerable<T> Filter<T>(this IEnumerable<T> self, Func<T, bool> predicate) {
    return self.Where(predicate);
}

Więcej szczegółów z https://github.com/cs-util-com/cscore#ienumerable-extensions :

wprowadź opis obrazu tutaj

CsUtil.com
źródło