[初心者向け]リスト操作関数map,reduce,filterの各言語の簡単なサンプル

各言語のリスト操作でよく使われるmap filter reduceの簡単な操作を並べてみました。

Javaは冗長ですね。Ruby と Haskellはすごく簡潔です。

ただし、私が普段の業務で使うのがJavaなので、他の言語のことをよく知らずですので、

もっと簡潔に書ける方法があるかもしれません。


  • Java 1.8

  • Ruby 2.6

  • Python 3.7

  • Haskell GHC version 8.0.1

  • Clojure 1.9.0

の簡単な例になります。


数値のリストを作る

ちなみに、業務では固定でリストを初期化することはあまりないと思われます。

普通はリスト系のデータはファクトリーメソッドにて生成されて参照すると思います。

ただし、私はテストなどでテストデータとして以下のような初期化をすることはあります。


Java

    List<Integer> xs = Arrays.asList(1, 2, 3, 4, 5);

//または @saka1029 さんに教えていただいた、Java 10以降なら
var xs = List.of(1, 2, 3, 4, 5);

//こんな無限リストを使うやり方もあります。業務ではこれもしない?
//外からseed値、function,limit値をいれて作れる。
xs = Stream.iterate(1, i -> i + 1).limit(5).collect(toList())



Ruby

    xs = [1, 2, 3, 4, 5]

# 実際には上はあまりよくない例であるらしく、
# @scivolaさんより教えていただいた以下の方が初期化としてはよいです。
xs = [*1..5]


Python

    xs = [1, 2, 3, 4, 5]



Haskell

    xs = [1, 2, 3, 4, 5]

-- または
xs = [1..5]


Clojure

    (def xs '(1 2 3 4 5))

;または @lagenorhynque さんにコメントいただいた方法
(def xs (range 1 (inc 5)))

以下このリストをすでに作っているものとします。


map 関数


リストをとって各値を2倍にする。

各言語とも結果は[2, 4, 6, 8, 10] になります。

print関数は省略します。


Java

    xs.stream().map(i -> i * 2).collect(toList());



Ruby

    xs.map {|i| i * 2}



Python

    list(map(lambda i: i * 2, xs))

# 多分この答えを出す場合、Pythonではリスト内包表記を使うのが普通と思われる。
[i * 2 for i in xs]


Haskell

    map (*2) xs



Clojure

    (map (fn [n] (* n 2)) xs)

; または@lagenorhynqueさんにおしえていただいたもの。こっちのが簡潔でいいですね!
(map #(* % 2) xs)


filter関数


偶数だけ選んで返す。

結果は[2, 4]になります。


Java

    xs.stream().filter(n -> n % 2 == 0).collect(toList());



Ruby

    xs.select(&:even?)



Python

    list(filter(lambda n: n % 2 == 0, xs))

#多分普通上のような書き方はせずリスト内包表記になると思います。
[n for n in xs if n % 2 == 0]


Haskell

    filter even xs



Clojure

    (filter even? xs)



reduce関数


リストの数字を加算して集約して返す。

結果は15になります。


Java

    xs.stream().reduce(Integer::sum).orElse(0);



Ruby


xs.reduce(:+)
#または l.inject(:+)
#reduce使わない場合
xs.sum

Pythonは@shiracamusさんよりimportがないとのことで不親切でしたので記載しました。


Python

    from functools import reduce

from operator import add

reduce(lambda a, b: a + b, xs)
# reduce使わない場合
sum(xs)
# または@shiracamusさんより教えていただきました、
reduce(add, xs)



Haskell

    foldl (+) 0 xs

-- fold使わない場合
sum xs


Clojure

    (reduce + xs)

;@lagenorhynqueさんより教えていただいた
(apply + xs)
;という書き方でも同じ結果です。内部で行われるのは (+ 1 2 3 4 5)
; reduceは(+ (+ (+ (+ 1 2) 3) 4) 5)

以上です。

いままで勉強したことのある言語に対して書きましたが、個人的に書いていて気持ちがいいと思ったのはRuby,Clojureです。

なんとなく感じが似ている気がします。(作者がどちらもlispが好きだから?)

Haskellはすごすぎて気持ち悪!(いい意味で)と思うところがあるのですが、楽しい!と思えるのはRuby,Clojureでしょうか?なぜなのかわかりませんが。またHaskellは考え方が他の言語とまるで違うのでなかなか勉強が進まないです。