プログラミング言語間のMap、Reduceの方法の比較
やっていること
- 1から10までの数字の配列を作成
- 偶数の値を取り出す
- 各値を2乗
- 合計する
- return 220
Java
IntStream.range(1, 11)
.filter(n -> n % 2 == 0)
.map(n -> n * n)
.sum();
Scala
Range(1, 11).filter { _ % 2 == 0 }
.map { n => n * n }
.sum
インラインで書こうとするとsum
が後置記法になってしまうので、代わりにreduce
。
(一応「慣用的かつ許容し得る」らしい)
Range(1, 11) filter { _ % 2 == 0 } map { n => n * n } reduce { _ + _ }
Scala的にはドットを省略するべきだそうだが、 複数行のメソッドチェーンだとエラーになってしまう。どうするのがいいんだろう...。
val seq = for (i <- 1 to 11 if i % 2 == 0) yield i * i
seq.sum
yieldを使う場合。
Kotlin
IntRange(1, 11).filter { n -> n.mod(2) == 0 }
.map { n -> n * n }
.reduce { r, n -> r + n }
Clojure
(reduce (fn [r n] (+ r n))
(map (fn [n] (* n n))
(filter (fn [n] (= (rem n 2) 0))
(range 1 11))))
マクロ
(->> (range 1 11)
(filter even?)
(map #(* % %))
(reduce #(+ %1 %2)))
内包表記
(reduce #(+ %1 %2)
(for [x (range 1 11) :when (even? x)]
(* x x)))
Python
# 3系だとreduceを使うのにimportが必要
from functools import reduce
num = list(range(1, 11))
even = filter(lambda n: n % 2 == 0, num)
pow = map(lambda n: n * n, even)
res = reduce(lambda r, n: r + n, pow)
res = sum([n * n for n in nums if n % 2 == 0])
内包表記を使う方がPythonっぽいんだろうか。インラインで書くのもPythonらしくない気がする。
Ruby
num = 1..11
even = num.select { |n| n.even? }
pow = num.map { |n| n * n } # collect
res = pow.reduce { |r, n| r + n } # inject
なんで同機能の異名メソッドがあるんですか(激怒)
PHP
$arr = range(1, 10); // inclusive
$even = array_filter($arr, function ($n) {
return $n % 2 == 0;
});
$pow = array_map(function ($n) {
return $n * $n;
}, $even);
// use array_sum() in production!
$res = array_reduce($pow, function ($rest, $n) {
return $rest + $n;
});
C#
var num = ImmutableList.Create(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
var even = num.Where(n => n % 2 == 0);
var pow = even.Select(n => n * n);
var res = pow.Sum();
LINQ
var pow = from n in Enumerable.Range(1, 11)
where n % 2 == 0
select n * n;
var res = pow.Aggregate((r, n) => r + n);
F#
let num = List.ofSeq(Enumerable.Range(1, 11))
let even = List.filter (fun n -> n % 2 = 0) num
let pow = List.map (fun n ->n * n) even
let res = List.reduce (fun r n -> r + n) pow
パイプライン演算子
[1..11]
|> List.filter (fun n -> n % 2 = 0)
|> List.map (fun n ->n * n)
|> List.sum
内包表記
[ for n in 1 .. 11 do if n % 2 = 0 then yield n * n] |> List.sum