Help us understand the problem. What is going on with this article?

【Ruby】mapの途中でnextを使用するとnilが入ってしまう罠

More than 1 year has passed since last update.

map(またはcollect)はブロックの戻り値を集めた配列を生成してくれる便利なメソッドです。
しかし、ブロックの途中でnextを使用すると意図せずnilが入ってしまう場合があるため、気をつける必要があります。

例えば以下のような数字の配列から偶数を取り出すメソッドを作成したとします。

qiita.rb
# 引数で渡した配列から偶数だけ取り出したい
def getEvenNumber(numArray)
  numArray.map do |num|
    next if num % 2 != 0
    num
  end
end

上記メソッドに対し、1〜5の整数の配列を引数に与えてみます。
この場合、2と4の配列が返ってくることが期待する結果です。

qiita.rb
getEvenNumber([1,2,3,4,5])
=> [nil, 2, nil, 4, nil]

2と4は期待通り返ってきたのですが、それ以外の要素がnilになってしまいました。
mapは配列の各要素に対して処理を行い、その結果を配列にして返却するため、もとの配列の数と生成された配列の要素数は等しくなります。そのため、途中でnextを入れて処理をスキップしたつもりでも、結果の配列にnilがセットされてしまうのです。

そこで、もしnilを配列に入れたくないのであれば、以下のようにmapした後にcompactを行うことで回避することができます。

qiita.rb
def getEvenNumber(numArray)
  numArray.map do |num|
    next if num % 2 != 0
    num
  end.compact
end

getEvenNumber([1,2,3,4,5])
=> [2, 4]

mapとcompactを使用しない別の方法としては、selectやrejectを使うのもありです。
もちろん使えない、使わない方が良いケースもあるので状況に応じてになりますが、今回のケースではこちらの方がシンプルですね。

qiita.rb
# selectを使う
def getEvenNumber(numArray)
  numArray.select do |num|
    num % 2 == 0
  end
end

# rejectを使う
def getEvenNumber(numArray)
  numArray.reject do |num|
    num % 2 != 0
  end
end

意図しないnilが含まれているとバグにも繋がるため、mapを使用する際はぜひ意識しておくと良いと思います。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした