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/

Tony
fonte
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

Joel Martinez
fonte
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

CsUtil.com
fonte