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

インデックスを基準にした配列のマージ

More than 3 years have passed since last update.

いぬです。よろしくおねがいします。

やりたいこと

配列をインデックス基準でマージしたいんじゃあ〜〜〜
そんでnilの時は無視するオプションとかほしいんじゃああ〜〜〜

# Array
foos = [1, 2]
bars = [3, nil, 4]
foos.deep_merge_by_index(bars, ignore_nil: true) # => [3, 2, 4] ←これ

# Hash
original = {foo: [1, 2, 3], bar: [4]}
diff     = {bar: [nil, 5]}
original.deep_merge(diff)                                            # => {foo: [1, 2, 3], bar: [nil, 5]} Valueが全部置き変わって死亡
original.deep_merge_with_keeping_array_index(diff, ignore_nil: true) # => {foo: [1, 2, 3], bar: [4, 5]} ←これ

ほうしん

  • ハッシュの中に配列があったり、その逆があったりするので、ArrayとHash両方のクラスにdeep_merge風のメソッドを生やす
  • Arrayのメソッドは自分で書かなくちゃいけないけど、Hashの方はdeep_mergeにブロック渡せるのでそれでなんとかする

こーど

Array.rb
class Array
  def deep_merge_by_index(other_array, ignore_nil: false)
    [count, other_array.count].max.times.map do |i|
      this_obj  = self[i]
      other_obj = other_array[i]

      if ignore_nil && other_obj.nil?
        this_obj
      elsif this_obj.is_a?(Hash) && other_obj.is_a?(Hash)
        this_obj.deep_merge_with_keeping_array_index(other_obj, ignore_nil: ignore_nil)
      elsif this_obj.is_a?(Array) && other_obj.is_a?(Array)
        this_obj.deep_merge_by_index(other_obj, ignore_nil: ignore_nil)
      else
        other_obj
      end
    end
  end
end
Hash.rb
class Hash
  def deep_merge_with_keeping_array_index(other_hash, ignore_nil: false)
    deep_merge(other_hash) do |_current_key, this_value, other_value|
      if ignore_nil && other_value.nil?
        this_value
      elsif this_value.is_a?(Array) && other_value.is_a?(Array)
        this_value.deep_merge_by_index(other_value, ignore_nil: ignore_nil)
      else
        other_value
      end
    end
  end
end

できた

もっとましな方法がある気がしてならない

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
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