概要
RubyのArray、Pythonのlistの典型的な操作のまとめ。
Python(Ruby)を学習し始めたばかりのRubyist(Pythonista)用の記事です。
参考 : C++版はこちら Ruby-C++ 配列操作の対応まとめ
前提条件
- Python 3.5.1
- Ruby 2.2.4
参考情報
- Ruby
- Python
メソッド
size
- ruby
[1,2,3].size #=> 3
- python
len( [1,2,3] ) #=> 3
each
要素に対してループを回す
- ruby
[1,2,3,4,5].each do |x|
puts 2*x #=> 2,4,6,8,10
end
- python
for x in [1,2,3,4,5]:
print(2*x)
each_with_index
indexと一緒にループを回す
- ruby
[5,4,3,2,1].each_with_index do |x,idx|
print "#{idx}:#{x}, "
end
# => 0:5, 1:4, 2:3, 3:2, 4:1,
- python
for idx,x in enumerate( [5,4,3,2,1] ):
print("{0}:{1}, ".format(idx,x), end="")
+
配列の結合
- ruby
-
concat
だと破壊的な操作,+
だと非破壊的操作
-
[1,2,3] + [4,5] # [1,2,3,4,5]
- python
-
extend
だと破壊的操作。+
だと非破壊的操作
-
[1,2,3] + [4,5]
push (<<)
末尾に要素を追加
- ruby
a = [1,2]
a << 3
# a => [1,2,3]
- python
a = [1,2]
a.append(3)
# a => [1,2,3]
map
- ruby
[1,2,3].map {|x| 2*x } #=> [2,4,6]
- python
-
map
関数を使ってもよいが、リスト内包表記がモダンらしい。
-
[ 2*x for x in [1,2,3] ] # => [2,4,6]
list( map( lambda x: 2*x, [1,2,3] ) ) # => [2,4,6]
find
- ruby
- 要素が見つからない場合はnilが返る
[7,8,9,10,11].find {|x| x%5 == 0 } #=> 10
- python
- あまり良い記法がみつからない
[ x for x in [7,8,9,10,11] if x % 5 == 0 ][0] #=> 10
- 追記: http://stackoverflow.com/questions/9868653/find-first-list-item-that-matches-criteria
- 第二引数はデフォルト値
next((x for x in [7,8,9,10,11] if x % 5 == 0), None)
find_all
- ruby
[1,2,3,4,5].find_all {|x| x>3 } #=> [4,5]
- python
- filterかリスト内包表記を使う
[ x for x in [1,2,3,4,5] if x > 3] #=> [4,5]
list( filter( lambda x: x>3, [1,2,3,4,5] ) ) #=> [4,5]
sort
- ruby
[4,1,3,2,5].sort #=> [1,2,3,4,5]
- python
sorted( [4,1,3,2,5] ) #=> [1,2,3,4,5]
sort_by
- ruby
[4,1,2,3,5].sort_by {|x| (3-x).abs } #=> [3,4,2,1,5]
- python
sorted( [4,1,3,2,5], key= lambda x: abs(3-x) )
index
- ruby
- 該当要素がなければnilが返る
[5,1,4,2,3].index(2) #=> 3
- python
- 該当要素がなければ例外が発生
[5,1,4,2,3].index(2) #=> 3
all?
- ruby
[2,4,6,8].all? {|x| x % 2 == 0 } #=> true
[2,4,6,9].all? {|x| x % 2 == 0 } #=> false
- python
all( x%2==0 for x in [2,4,6,8] ) #=> True
all( x%2==0 for x in [2,4,6,9] ) #=> False
sum
- ruby
- injectを使う
[1,3,5].inject(:+) #=> 9
- python
- 組み込み関数sumを使う
sum( [1,3,5] )
inject (reduce)
- ruby
[1,2,3,4,5].inject(1) {|acc,x| acc*x } #=> 120
[1,2,3,4,5].inject("") {|acc,x| acc + (x%2==0?'e':'o') } #=> oeoeo
- python
- reduce関数を使う。Python2までは組み込み関数。Python3からは
functools
をimportする必要がある。
- reduce関数を使う。Python2までは組み込み関数。Python3からは
import functools
functools.reduce( lambda acc,x: acc*x, [1,2,3,4,5], 1 )
functools.reduce( lambda acc,x: acc+("e" if x%2==0 else "o") , [1,2,3,4,5], "" )
uniq
- ruby
[5,1,1,2,3,5,5].uniq #=> [5,1,2,3]
- python
- setに入れてからlistに変換する。順番は保存されない。
- 順番を保存したい場合は、ループを回すしかないようだ。
list( set( [5,1,1,2,3,5,5] ) )
li_uniq = []
for x in [5,1,1,2,3,5,5]:
if x not in li_uniq:
li_uniq.append(x)
li_uniq #=> [5,1,2,3]
uniq {block}
- ruby
- ブロックを評価した結果が重複しているものを削除する
[4,5,1,2,3,4,5].uniq {|x| x % 3 } #=> [4,5,3]
- python
li_uniq = []
set_uniq = set()
for x in [4,5,1,2,3,4,5]:
if x % 3 not in set_uniq:
li_uniq.append(x)
set_uniq.add(x%3)
li_uniq #=> [4,5,3]
join
- ruby
[1,5,3,2].join(":") #=> "1:5:3:2"
- python
- Stringに
join
メソッドがあるというのが非常にわかりづらい。配列は文字列型に明示的に変換しなくてはならない。
- Stringに
":".join(map(str, [1,5,3,2]))
reverse
- ruby
[1,2,3].reverse #=> [3,2,1]
a = [1,2,3]
a.reverse!
a #=> [3,2,1]
- python
- Listのreverseメソッドは破壊的操作。
- 非破壊的な操作は組み込み関数の
reversed
を使う。
list( reversed([1,2,3]) )
a = [1,2,3]
a.reverse()
a #=> [3,2,1]
group_by
- ruby
["cat","bat","bear","camel","alpaca"].group_by {|x| x[0]}
# {"c"=>["cat", "camel"], "b"=>["bat", "bear"], "a"=>["alpaca"]}
- python
- ループを回してdictionaryに要素を追加していく
d = {}
for x in ["cat","bat","bear","camel","alpaca"]:
key = x[0]
if key not in d:
d[key] = []
d[key].append(x)
d # => {'c': ['cat', 'camel'], 'a': ['alpaca'], 'b': ['bat', 'bear']}
shuffle
- ruby
[1,2,3,4,5,6,7].shuffle #=> [2, 6, 4, 7, 5, 3, 1]
- python
import random
a = [1,2,3,4,5,6,7]
random.shuffle(a)
a #=> [4, 5, 6, 2, 7, 1, 3]