Карта та скорочення в .NET


Відповіді:


298

Еквіваленти Linq Map і Reduce: Якщо вам пощастило мати linq, вам не потрібно писати власну карту та зменшувати функції. C # 3.5 і Linq вже має його, хоч і під різними назвами.

  • Карта Select:

    Enumerable.Range(1, 10).Select(x => x + 2);
  • Скорочення Aggregate:

    Enumerable.Range(1, 10).Aggregate(0, (acc, x) => acc + x);
  • Фільтр Where:

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

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


1
Переклад правильний, але він не містить ключового моменту. Крок зміни розміру в зменшенні карти є критичним при зменшенні карти, але не відображається в імені, а для нього не потрібно писати жодного коду. Він керується виключно ключем, який витягується на кроці карти. Відповідь Джоеля Мартінеса підкреслює, що на мій погляд краще.
xtofs

2
Посилання не працює, правильне посилання є: justinshield.com/2011/06/mapreduce-in-c
Олександру-Дан Поп

12
Чому о, чому вони просто не називають це Reduceзамість Aggregate... MS просто любить дратувати програмістів
John Henckel

13
@JohnHenckel, я точно не є авторитетним джерелом, але я впевнений, що це походить від SQL. Я вважаю, що linq був оригінальним, купленим як спосіб полегшити взаємодію з sql у C #. Коли ви називаєте функції у цьому світі, агрегат починає звучати трохи звичніше, ніж "зменшувати" у порівнянні з такими речами, як "Вибір" та "Групувати за". Я не кажу, що це правильно, це мене дратує до кінця, але я гадаю, що це причина цього.
Елліот Блекберн

18

Класи задач, які добре підходять для рішення стилю mapreduce, є проблемами агрегації. Вилучення даних із набору даних. У C # можна скористатися LINQ для програмування в цьому стилі.

З наступної статті: http://codecube.net/2009/02/mapreduce-in-c-using-linq/

Метод GroupBy виконує функцію карти, тоді як метод Select виконує роботу щодо зменшення проміжних результатів у остаточний список результатів.

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

Для розподіленої частини ви можете перевірити DryadLINQ: http://research.microsoft.com/en-us/projects/dryadlinq/default.aspx


3

Оскільки я ніколи не пам'ятаю, що LINQ називає це Where, Selectа Aggregateзамість цього Filter, Mapі Reduceтому я створив кілька методів розширення, якими ви можете скористатися:

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

Ось 3 методи (з 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);
}

Ще кілька деталей з https://github.com/cs-util-com/cscore#ienumerable-extensions :

введіть тут опис зображення

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.