LoginSignup
23
25

More than 5 years have passed since last update.

JavaScriptとRubyのArrayのメソッドの比較

Last updated at Posted at 2014-03-21

2つを交互に書いてるとよくこんがらがるので比較してみた。
JavaScriptはES5相当です。

要素を追加

javascript
var arr = [1, 2, 3];

arr.push(4);
// [1, 2, 3, 4]

arr.unshift(0);
// [0, 1, 2, 3, 4]

arr.splice(2, 0, 9);
// [0, 1, 9, 2, 3, 4]
ruby
arr = [1, 2, 3]

arr.push(4)
# arr << 4 でもいい
# [1, 2, 3, 4]

arr.unshift(0)
# [0, 1, 2, 3, 4]

arr.insert(2, 9)
# [0, 1, 9, 2, 3, 4]

使い方としては大体同じだけど戻り値が結構違う。

js
var arr = [1, 2, 3];
arr.push(4);

これは4で配列の長さが返される。

ruby
arr = [1, 2, 3]
arr.push(4)

これは[1, 2, 3, 4]でレシーバ自身が返される。時々ハマる。

あとjsのsplice()はかなり多機能でいろいろ使える。

pop, shift

js
[1, 2, 3].pop() // 3が返る 
[1, 2, 3].shift() // 1が返る
ruby
[1, 2, 3].pop # 3が返る
[1, 2, 3].shift # 1が返る

これは使い方も戻り値も大体一緒。

配列の検索

js
[1, 2, 1, 3].indexOf(1);
// 0
[1, 2, 1, 3].lastIndexOf(1);
// 2
ruby
[1, 2, 1, 3].index(1)
# 0
[1, 2, 1, 3].rindex(1)
# 2

見つからない場合はindexOf()は-1を返す。index()はnilを返す。
rubyはfind_index()でもおなじ。

配列に特定の値が含まれるか

js
[1, 2, 3].indexOf(2) >= 0
// true
ruby
[1, 2, 3].include? 2
# true

rubyはindex()がnil返すのでindex()でもいいといえばいいけど、せっかくあるのでinclude?使ったほうが多分いいと思います。

指定位置の要素の取り出し

js
[1, 2, 3, 4].slice(1, 3);
// [2, 3]
[1, 2, 3, 4].slice(1, -1); // 後ろからの指定も出来る
ruby
[1, 2, 3, 4].slice(1, 2)
# [2, 3]
[1, 2, 3, 4][1..2]

見た目は近いけれど、jsはslice(begin, end)で始点と終点の指定なのに対して、rubyだとslice(index, length)で長さ指定なのでたまに混乱する。
実際はrubyだとRangeを使うのをよく見る感じ。

指定位置の要素の削除

js
var arr = [1, 2, 3, 4];
arr.splice(1, 1);
// arr = [1, 3, 4]
arr = [1, 2, 3, 4];
arr.splice(1, 2);
// arr = [1, 4]
ruby
arr = [1, 2, 3, 4]
arr.delete_at(1)
# arr = [1, 3, 4]
arr = [1, 2, 3, 4]
arr[1..2] = []
# arr = [1, 4]

jsはsplice()の引数を省略すれば削除できる。
rubyは一つならdelete_at()で削除できる。複数の場合は空の配列を代入して削除できる。あとrubyは上記に加えて、

ruby
arr = [1, 2, 3, 4]
arr.delete(2)
# arr = [1, 3, 4]

みたいにdelete(val)で直接値を指定して消すのができる。

指定位置の要素の置き換え

js
var arr = [1, 2, 3, 4];
arr.splice(1, 2, 0, 1);
// arr = [1, 0, 1, 4]
ruby
arr = [1, 2, 3, 4]
arr[1, 2] = [0, 1]
# arr = [1, 0, 1, 4]

splice()相当のメソッドはrubyにないので指定部分を取り出して[]=で直接入れる。splice()は結構便利。

配列を空に

js
var arr = [1, 2, 3];
arr.length = 0;
// arr = []
ruby
arr = [1, 2, 3]
arr.clear
# arr = []

jsだとlengthに0を入れるのがいいらしい。arr.splice(0, arr.length);ってやって全部置換しても空にできる。

配列を複製

js
var arr1 = [1, 2, 3];
var arr2 = arr.slice(0);
// arr1 = [1, 2, 3], arr2 = [1, 2, 3]
ruby
arr1 = [1, 2, 3]
arr2 = arr.clone # arr.dupでもできる
# arr1 = [1, 2, 3], arr2 = [1, 2, 3]

どっちも浅いコピーになる。深いコピーしたい時はjsだとJSON.stringify()してparseである程度できる。rubyはMarshal.dump()してloadする。

他の配列と結合

js
[1, 2].concat([3, 4]);
// [1, 2, 3, 4]
ruby
arr = [1, 2]
arr.concat([3, 4]) # レシーバ自身が変更される(arr = [1, 2, 3, 4])
arr + [3, 4] # レシーバ自身は変更されない(arr = [1, 2])
# [1, 2, 3, 4]

rubyだとconcat()でレシーバ自身が変更される。jsは変更されないで新しい配列を返すので、動作としては+で結合した場合に近い感じ。
jsはArray.prototype.push.apply()の方が速いって聞いた時もあるけどよくわからない。

ソートする

js
[2, 1, 4, 3].sort(); // 昇順ソート
// [1, 2, 3, 4]
[2, 1, 4, 3].sort(function(a, b) { return b - a }); // 降順ソート
// [4, 3, 2, 1]
ruby
[2, 1, 4, 3].sort # 昇順ソート
# [1, 2, 3, 4]
[2, 1, 4, 3].sort {|a, b| b <=> a} # 降順ソート
# [4, 3, 2, 1]

比較関数の書き方ががちょっと違う感じで、rubyは基本的に<=>演算子を使って書く。
ただjsもrubyも、
a > b のとき 正の数
a == b のとき 0
a < b のとき 負の数
を返すような関数を渡してあげればちゃんと動く。

foreach的なやつ

js
[1, 2, 3].forEach(function(el) { console.log(el) });
[1, 2, 3].forEach(function(el, idx) { console.log(el, idx) }); // インデックス付き
ruby
[1, 2, 3].each {|el| puts el}
[1, 2, 3].each.with_index {|el, idx| puts el, idx} # インデックス付き

functionとブロックの違いなだけで基本的には大体一緒。
jsはこういうの使う時、function(value, index, array) {}で要素, インデックス, 元の配列を受け取れる。
rubyはそのままだと要素だけなので、インデックス使いたいときはwith_indexする。(よく忘れる)

要素それぞれに関数を適用

js
[1, 2, 3].map(function(el) { return el + 1 });
ruby
[1, 2, 3].map {|el| el + 1} # collectでもいい

大体似てるけど、順番に書いてるとjsでreturnを忘れ、rubyでreturnを書いてしまうことがよくある。(俺調べ)

条件をみたす要素を取り出す

js
[0, -2, 1].filter(fuction(el) { return el >= 0 });
ruby
[0, -2, 1].select {|el| el >= 0}

名前以外はほぼ一緒。

条件をみたす要素があるか

js
[0, -2, 1].some(fuction(el) { return el < 0 });
ruby
[0, -2, 1].any? {|el| el < 0}

名前以外は(ry

すべての要素が条件をみたすか

js
[0, -2, 1].every(function(el) { return el < 0 });
ruby
[0, -2, 1].all? {|el| el < 0}

名前(ry

隣り合う要素に順番に関数を適用

js
[1, 2, 3].reduce(function(p, c) { return p + c });
[1, 2, 3].reduce(function(p, c) { return p + c }, 10); // 初期値として10
ruby
[1, 2, 3].reduce {|p, c| p + c} # injectでもいい
[1, 2, 3].reduce(10) {|p, c| p + c} # 初期値として10

初期値の与え方がちょっと違うけど、基本的には大体一緒。

ユニークな要素のみ取り出し

js
[1, 2, 2, 3, 3].filter(function(val, idx, arr) {
  return arr.indexOf(val) === idx;
});
// [1, 2, 3]
ruby
[1, 2, 2, 3, 3].uniq
# [1, 2, 3]

rubyはそのままのメソッドがある。
jsはfilter()indexOf()で書ける。

二次元配列っぽいのとかを一次元にする

js
[[0, 1], [2, 3], [4, 5]].reduce(function(p, c) {
  return p.concat(c);
});
// [0, 1, 2, 3, 4, 5]
ruby
[[0, 1], [2, 3], [4, 5]].flatten
# [0, 1, 2, 3, 4, 5]

jsはreduceとconcatで書ける。

参考:
Array - JavaScript | MDN
Rubyリファレンスマニュアル - class Array

23
25
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
25