Clojure・JavaScript・C#・Python・Elispでシーケンス操作の仕方を対比してまとめた。
map, filter, reduceとか使いたいと思ったときに、言語ごとに違うので自分用にまとめたい。
map fn seq
シーケンスの1つ1つに関数を適用した結果のシーケンスを返す
例) [1, 2, 3, 4] = inc => [2, 3, 4, 5]
(def s [1 2 3 4])
(def t (map #(inc %) s))
(println t) => (2, 3, 4, 5)
let s = [1, 2, 3, 4]
let t = s.map(x => x + 1)
console.log(t) => [2, 3, 4, 5]
map
じゃなくてSelect
using System;
using System.Collections.Generic;
using System.Linq;
public class Hello {
public static void Main(){
var s = new List<int>(){ 1, 2, 3, 4 };
var t = s.Select(x => x + 1);
System.Console.WriteLine(string.Join(",", t)); => 2,3,4,5
}
}
list()
で実体化が必要なのに注意。s = [1, 2, 3, 4]
t = map(lambda x: x + 1, s)
print(list(t)) => [2, 3, 4, 5]
t
はtrueの意味で予約されているmap
ではなくmapcar
なのはなんで?mapc
もあるseq-map
というのもあるseq-
族に合わせて再定義されているものと思われる。(setq s '(1 2 3 4))
(setq l (mapcar '1+ s))
(print l) => (2, 3, 4, 5)
filter fn seq
シーケンスの1つ1つに関数を適用した結果trueのものに絞ったシーケンスを返す。
例) [1, 2, 3, 4] = even => [2, 4]
(def s [1 2 3 4])
(def t (filter #(even? %) s))
(println t) => (2, 4)
let s = [1, 2, 3, 4]
let t = s.filter(x => x % 2 == 0)
console.log(t) => [2, 4]
fliter
じゃなくてWhere
using System;
using System.Collections.Generic;
using System.Linq;
public class Hello {
public static void Main(){
var s = new List<int>(){ 1, 2, 3, 4 };
var t = s.Where(x => x % 2 == 0);
System.Console.WriteLine(string.Join(",", t)); => 2,4
}
}
list()
で実体化が必要なのに注意。s = [1, 2, 3, 4]
t = filter(lambda x: x % 2 == 0, s)
print(list(t)) => [2, 4]
seq-filter
という名前になっている。(setq s '(1 2 3 4))
(setq l (seq-filter (lambda (x) (= (% x 2) 0)) s))
(print l) => (2 4)
reduce fn seq
シーケンスを前から順番に取り出したものと、前回の結果を引数にとって関数を呼び、1つの結果を返す。
例) [1, 2, 3, 4] = + => 10
(def s [1 2 3 4])
(def t (reduce + s))
(println t) => 10
let s = [1, 2, 3, 4]
let t = s.reduce((a, b) => a + b)
console.log(t) => 10
reduce
じゃなくてAggregate
。using System;
using System.Collections.Generic;
using System.Linq;
public class Hello {
public static void Main(){
var s = new List<int>(){ 1, 2, 3, 4 };
var t = s.Aggregate((a, b) => a + b);
System.Console.WriteLine(string.Join(",", t)); => 10
}
}
reduce
は別途インポートが必要。from functools import reduce
s = [1, 2, 3, 4]
t = reduce(lambda a, b: a + b, s)
print(t) => 10
seq-reduce
という名前になっている。(setq s '(1 2 3 4))
(setq l (seq-reduce '+ s 0))
(print l) => 10
filter
とfirst
の組み合わせ。nil
になる。(def s [1 2 3 4])
(def t (first (filter #(= % 1) s)))
(println t) => 1
let s = [1, 2, 3, 4]
let t = s.find(x => x == 1)
console.log(t) => 1
First
とFirstOrDefault
がある。FirstOrDefault
はマッチしなかったとき例外にならず、その型のDefault値を返す。using System;
using System.Collections.Generic;
using System.Linq;
public class Hello {
public static void Main(){
var s = new List<int>(){ 1, 2, 3, 4 };
var t = s.FirstOrDefault(x => x == 1);
System.Console.WriteLine(t); => 1
}
}
filter
とインデックスアクセスする。s = [1, 2, 3, 4]
t = list(filter(lambda x: x == 1, s))[0]
print(t) => 1
seq-find
という名前になっている。(setq s '(1 2 3 4))
(setq l (seq-find (lambda (x) (= x 1)) s))
(print l)
(def s [1 2 3 4])
(def t (every? #(< 0 %) s))
(println t) => true
let s = [1, 2, 3, 4]
let t = s.every(x => 0 < x)
console.log(t)
every
じゃなくてAll
。using System;
using System.Collections.Generic;
using System.Linq;
public class Hello {
public static void Main(){
var s = new List<int>(){ 1, 2, 3, 4 };
var t = s.All(x => 0 < x);
System.Console.WriteLine(t); => true
}
}
s = [1, 2, 3, 4]
t = all(map(lambda x: 0 < x, s))
print(t) => true
リスト内包表記を使うのが一般的みたい(読みにくくて個人的には嫌いだけど)
s = [1, 2, 3, 4]
t = all(0 < x for x in s)
print(t) => true
seq-every-p
という名前になっている-p
がついてるのはpredicate述語の略で、Clojureだと?
を付ける。((setq s '(1 2 3 4))
(setq l (seq-every-p (lambda (x) (< 0 x)) s))
(print l)
some
はちょっと特殊で、?
がついてないので、trueでないときにnil
が返ってくる。(boolean x)
をかませる必要がある。(def s [1 2 3 4])
(def t (boolean (some #(< 0 %) s)))
(println t) => true
let s = [1, 2, 3, 4]
let t = s.some(x => 0 < x)
console.log(t) => true
some
じゃなくてAny
using System;
using System.Collections.Generic;
using System.Linq;
public class Hello {
public static void Main(){
var s = new List<int>(){ 1, 2, 3, 4 };
var t = s.Any(x => 0 < x);
System.Console.WriteLine(t); => true
}
}
s = [1, 2, 3, 4]
t = any(map(lambda x: 0 < x, s))
print(t) => true
リスト内包表記を使うのが一般的みたい(読みにくくて個人的には嫌いだけど)
s = [1, 2, 3, 4]
t = any(0 < x for x in s)
print(t) => true
seq-some
という名前になっている。-p
がついていないのは、戻り値が条件の関数の戻り値に依存するため。(setq s '(1 2 3 4))
(setq l (seq-some (lambda (x) (< 1 x)) s))
(print l) => t
言語ごとに呼び方違ったりして検索がいつも戸惑う。
なんだかんだJavaScriptの呼び名に慣れちゃってる感があるのでJavaScriptの呼び名に対応で書いた。
動作確認にはpiza.ioが便利だった。
Clojureのシーケンス操作も迷うのでチートシート作りたい。