Mappa e riduci in .NET


Risposte:


299

Equivalenti Linq di Mappa e Riduci: se sei abbastanza fortunato da avere Linq, non è necessario scrivere la tua mappa e ridurre le funzioni. C # 3.5 e Linq lo hanno già seppur con nomi diversi.

  • La mappa è Select:

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

    Enumerable.Range(1, 10).Aggregate(0, (acc, x) => acc + x);
  • Il filtro è Where:

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

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


1
La traduzione è corretta ma manca un punto chiave. Il passaggio shuffle nella riduzione della mappa è fondamentale nella riduzione della mappa, ma non viene visualizzato nel nome e non è necessario scrivere alcun codice per esso. È guidato esclusivamente dalla chiave che viene estratta nel passaggio della mappa. La risposta di Joel Martinez sottolinea che, a mio avviso, è meglio.
xtofs,

2
Il link non funziona, il link corretto è: justinshield.com/2011/06/mapreduce-in-c
Alexandru-Dan Pop

12
Perché oh perché non lo chiamano Reduceinvece di Aggregate... A MS piace infastidire i programmatori
John Henckel,

13
@JohnHenckel, sicuramente non sono una fonte autorevole, ma sono abbastanza sicuro che provenga da SQL. Credo che linq sia stato acquistato originariamente come un modo per rendere più semplice l'interazione con sql in C #. Quando si nominano le funzioni in quel mondo, l'aggregato inizia a sembrare un po 'più familiare di "riduci" rispetto a cose come Seleziona e Raggruppa per. Non sto dicendo che è giusto, mi infastidisce senza fine ma immagino che sia la ragione.
Elliot Blackburn,

18

Le classi di problemi che ben si adattano a una soluzione di stile mapreduce sono problemi di aggregazione. Di estrarre dati da un set di dati. In C #, si potrebbe sfruttare LINQ per programmare in questo stile.

Dal seguente articolo: http://codecube.net/2009/02/mapreduce-in-c-using-linq/

il metodo GroupBy funge da mappa, mentre il metodo Select svolge il compito di ridurre i risultati intermedi nell'elenco finale dei risultati.

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);

Per la parte distribuita, è possibile consultare DryadLINQ: http://research.microsoft.com/en-us/projects/dryadlinq/default.aspx


3

Dal momento che non ricordo mai che LINQ lo chiama Where, Selecte Aggregateinvece di Filter, Mape Reducecosì ho creato alcuni metodi di estensione che puoi usare:

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

Ecco i 3 metodi (da 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);
}

Alcuni dettagli in più da https://github.com/cs-util-com/cscore#ienumerable-extensions :

inserisci qui la descrizione dell'immagine

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.