各言語のリスト操作でよく使われる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
の簡単な例になります。
数値のリストを作る
ちなみに、業務では固定でリストを初期化することはあまりないと思われます。
普通はリスト系のデータはファクトリーメソッドにて生成されて参照すると思います。
ただし、私はテストなどでテストデータとして以下のような初期化をすることはあります。
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())
xs = [1, 2, 3, 4, 5]
# 実際には上はあまりよくない例であるらしく、
# @scivolaさんより教えていただいた以下の方が初期化としてはよいです。
xs = [*1..5]
xs = [1, 2, 3, 4, 5]
xs = [1, 2, 3, 4, 5]
-- または
xs = [1..5]
(def xs '(1 2 3 4 5))
;または @lagenorhynque さんにコメントいただいた方法
(def xs (range 1 (inc 5)))
以下このリストをすでに作っているものとします。
map 関数
リストをとって各値を2倍にする。
各言語とも結果は[2, 4, 6, 8, 10]
になります。
print関数は省略します。
xs.stream().map(i -> i * 2).collect(toList());
xs.map {|i| i * 2}
list(map(lambda i: i * 2, xs))
# 多分この答えを出す場合、Pythonではリスト内包表記を使うのが普通と思われる。
[i * 2 for i in xs]
map (*2) xs
(map (fn [n] (* n 2)) xs)
; または@lagenorhynqueさんにおしえていただいたもの。こっちのが簡潔でいいですね!
(map #(* % 2) xs)
filter関数
偶数だけ選んで返す。
結果は[2, 4]
になります。
xs.stream().filter(n -> n % 2 == 0).collect(toList());
xs.select(&:even?)
list(filter(lambda n: n % 2 == 0, xs))
#多分普通上のような書き方はせずリスト内包表記になると思います。
[n for n in xs if n % 2 == 0]
filter even xs
(filter even? xs)
reduce関数
リストの数字を加算して集約して返す。
結果は15
になります。
xs.stream().reduce(Integer::sum).orElse(0);
xs.reduce(:+)
#または l.inject(:+)
#reduce使わない場合
xs.sum
Pythonは@shiracamusさんよりimportがないとのことで不親切でしたので記載しました。
from functools import reduce
from operator import add
reduce(lambda a, b: a + b, xs)
# reduce使わない場合
sum(xs)
# または@shiracamusさんより教えていただきました、
reduce(add, xs)
foldl (+) 0 xs
-- fold使わない場合
sum xs
(reduce + xs)
;@lagenorhynqueさんより教えていただいた
(apply + xs)
;という書き方でも同じ結果です。内部で行われるのは (+ 1 2 3 4 5)
; reduceは(+ (+ (+ (+ 1 2) 3) 4) 5)
以上です。
いままで勉強したことのある言語に対して書きましたが、個人的に書いていて気持ちがいいと思ったのはRuby,Clojureです。
なんとなく感じが似ている気がします。(作者がどちらもlispが好きだから?)
Haskellはすごすぎて気持ち悪!(いい意味で)と思うところがあるのですが、楽しい!と思えるのはRuby,Clojureでしょうか?なぜなのかわかりませんが。またHaskellは考え方が他の言語とまるで違うのでなかなか勉強が進まないです。