Mapear e reduzir no .NET


Respostas:


298

Equivalentes a Linq de Map and Reduce: Se você tiver a sorte de ter linq, não precisará escrever seu próprio mapa e reduzir as funções. O C # 3.5 e o Linq já o possuem, embora com nomes diferentes.

  • O mapa é Select:

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

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

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

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


1
A tradução está correta, mas perde um ponto-chave. A etapa de reprodução aleatória na redução de mapa é crítica na redução de mapa, mas não aparece no nome e não é necessário escrever nenhum código para ela. Ele é direcionado exclusivamente pela chave extraída na etapa do mapa. A resposta de Joel Martinez destaca isso na minha opinião melhor.
— Xtofs

2
Link não funcionar, link correto é: justinshield.com/2011/06/mapreduce-in-c
— Alexandru-Dan Pop

12
Por que oh por que eles não apenas chamá-lo Reduce, em vez de Aggregate... MS só gosta de programadores irrite
— John Henckel

13
@ JohnHenckel, definitivamente não sou uma fonte autorizada, mas tenho certeza de que isso vem do SQL. Acredito que o linq foi originalmente comprado como uma maneira de facilitar a interação com o sql em c #. Quando você está nomeando funções nesse mundo, o agregado começa a parecer um pouco mais familiar do que "reduzir" quando comparado a itens como Selecionar e Agrupar por. Não estou dizendo que está certo, isso me irrita sem fim, mas imagino que seja a razão disso.
— Elliot Blackburn

18

As classes de problemas que são adequadas para uma solução no estilo mapreduce são problemas de agregação. De extração de dados de um conjunto de dados. Em C #, pode-se tirar proveito do LINQ para programar nesse estilo.

Do seguinte artigo: http://codecube.net/2009/02/mapreduce-in-c-using-linq/

o método GroupBy está atuando como o mapa, enquanto o método Select faz o trabalho de reduzir os resultados intermediários na lista final de resultados.

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

Para a parte distribuída, você pode conferir o DryadLINQ: http://research.microsoft.com/en-us/projects/dryadlinq/default.aspx


3

Desde que eu nunca pode lembrar que LINQ chama isso Where, Selecte Aggregateem vez de Filter, Mape Reduceentão eu criei alguns métodos de extensão que você pode usar:

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

Aqui estão os três métodos (em 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);
}

Mais alguns detalhes em https://github.com/cs-util-com/cscore#ienumerable-extensions :

insira a descrição da imagem aqui

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.