配列の中で重複していないものだけを合計する
やりたいこと
Rubyで、配列で渡される数値の合計値を出力するメソッドが作りたい。 ただし、渡された配列内で値が重複している数字は除いて合計を計算する。
出力例
lone_sum([1, 2, 3]) # → 6 lone_sum([3, 2, 3]) # → 2 lone_sum([3, 3, 3]) # → 0
最初に考えたこと
- シンプルに配列をループで回せばできそうだが、つまらない
- 一行でバシッと返せたらかっこいい(可読性はきっとサイテーだけど)
次の手順でできそう。
1. 数字ごとにグルーピングする
2. 数字ごとに何個ずつ含まれているかをハッシュで表す
3. 得られたハッシュから、個数が1個のもののみを取り出して配列にする
4. 配列の合計を計算する
できた!
パフォーマンスに関しては未調査です。
def lone_sum(arr) puts arr.group_by{|i| i}.select{|k,v| v.length == 1}.keys.sum end
調査したこと
まずは1. 数字ごとにグルーピングする
と2. 数字ごとに何個ずつ含まれているかをハッシュで表す
から。
配列.group_by
array.group_by {|i| 式}
で、ブロックの式を評価した結果でグルーピングしてくれる。戻り値はハッシュ構造になる。
instance method Enumerable#group_by
次に、3. 得られたハッシュから、個数が1個のもののみを取り出して配列にする
をやっていく。
手順は2つに分けられる:
1. ハッシュに「個数=1個」でフィルタをかける
2. フィルタを通過した要素のキーのみを取り出して配列にする
ハッシュ.select
keyとvalueのペアについてブロックを評価して、合格する(trueを返す)ものだけを含むハッシュを返してくれる。
ハッシュ.keys
ハッシュからkeyのみを取り出し、配列にして返してくれる
最後に、4. 配列の合計を計算する
でキメる。
配列.sum
後記
Rubyの文法練習のために、あえてなるべく複雑な方法でやってみました。案の定可読性は落ちています。 しかし、知らないメソッドを調べながら一つ一つ積み上げていく感覚が快感ですね。