Mapper et réduire dans .NET

Réponses:

299

Equivalents Linq de Map et Reduce: Si vous avez la chance d'avoir linq, vous n'avez pas besoin d'écrire votre propre carte et de réduire les fonctions. C # 3.5 et Linq l'ont déjà sous des noms différents.

  • La carte est Select:

    Enumerable.Range(1, 10).Select(x => x + 2);
  • Réduire c'est Aggregate:

    Enumerable.Range(1, 10).Aggregate(0, (acc, x) => acc + x);
  • Le filtre est Where:

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

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

Tony
la source
1
La traduction est correcte mais elle manque un point clé. L'étape de shuffle dans la réduction de carte est critique dans la réduction de carte mais n'apparaît pas dans le nom et il n'est pas nécessaire d'écrire de code pour cela. Il est uniquement piloté par la clé extraite à l'étape de la carte. La réponse de Joel Martinez souligne que, à mon avis, mieux.
xtofs
2
Le lien ne fonctionne pas, le lien correct est: justinshield.com/2011/06/mapreduce-in-c
Alexandru-Dan Pop
12
Pourquoi oh pourquoi ne l'appellent-ils pas Reduceau lieu de Aggregate... MS aime juste ennuyer les programmeurs
John Henckel
13
@JohnHenckel, je ne suis certainement pas une source faisant autorité, mais je suis presque sûr que cela vient de SQL. Je crois que linq a été acheté à l'origine pour faciliter l'interaction avec SQL en C #. Lorsque vous nommez des fonctions dans ce monde, l'agrégat commence à sembler un peu plus familier que «réduire» par rapport à des éléments tels que Sélectionner et Regrouper par. Je ne dis pas que c'est vrai, ça m'ennuie sans fin, mais j'imagine que c'est la raison.
Elliot Blackburn
18

Les classes de problèmes qui conviennent bien pour une solution de style mapreduce sont des problèmes d'agrégation. D'extraction de données à partir d'un ensemble de données. En C #, on pourrait profiter de LINQ pour programmer dans ce style.

De l'article suivant: http://codecube.net/2009/02/mapreduce-in-c-using-linq/

la méthode GroupBy agit comme la carte, tandis que la méthode Select fait le travail de réduire les résultats intermédiaires dans la liste finale des résultats.

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

Pour la partie distribuée, vous pouvez consulter DryadLINQ: http://research.microsoft.com/en-us/projects/dryadlinq/default.aspx

Joël Martinez
la source
3

Puisque je ne peux pas oublier que LINQ appelle Where, Selectet au Aggregatelieu de Filter, Mapet Reducedonc je créé quelques méthodes d'extension , vous pouvez utiliser:

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

Voici les 3 méthodes (depuis 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);
}

Quelques détails supplémentaires sur https://github.com/cs-util-com/cscore#ienumerable-extensions :

entrez la description de l'image ici

CsUtil.com
la source