0

ruby でミューテーションを伴う反復コードを書くとき、私はしばしばこのパターンに従っていることに気がつきます。

def build_x some_data
  x = [] # or x = {}
  some_data.each do |data|
    x.some_in_place_update! (... data ...)
  end
  x
end

(xと同じ形にならないことが多いsome_dataので、単純なものでmapはダメです。)

このパターンに従うコードを書くためのより慣用的な、またはより良い方法はありますか?


[編集] 実際の例:

def to_hierarchy stuff
  h = {}
  stuff.each do |thing|
    path = thing.uri.split("/").drop(4)
    sub_h = h
    path.each do |segment|
      sub_h[segment] ||= {}
      sub_h = sub_h[segment]
    end
    sub_h.merge!(
      data: thing.data,
    )
  end
  h
end

thingこれは、関連しているが異なる を持っている のフラットなリストから始まりますuri。このフラット リストを階層に変換しthing、 の同じ を共有する関連する をグループ化segmenturiます。これは私が説明したパターンに従います: initialize h、いくつかのデータをループしh、途中で変更し、最後に吐き出しhます。

[edit2] 別の関連例

def count_data obj
  i = if obj[:data] then 1 else 0
  obj.each do |k, v|
    i += count_statements v unless :data == k
  end
  i
end
4

2 に答える 2

1

あなたのto_hierarchy例は次のように行うことができますeach_with_object

def to_hierarchy stuff
  stuff.each_with_object({}) do |thing, h|
    #...
  end
end

each_with_object余分なオブジェクトをブロックに渡し、反復が完了するとそのオブジェクトを返します。

あなたが伝統主義者であれば、次のように使用できますinject

def to_hierarchy stuff
  stuff.inject({}) do |h, thing|
    #...
    h
  end
end

ブロック引数の順序の変更と、次のブロック呼び出しにフィードバックできるhように、ブロックが戻る必要があることに注意してください。inject

あなたの一般的な例は次のように書くことができます:

def build_x some_data
  some_data.each_with_object([]) do |data, x|
    x.some_in_place_update! (... data ...)
  end
end

また:

def build_x some_data
  some_data.inject({}) do |x, data|
    x.some_in_place_update! (... data ...)
    x
  end
end
于 2013-09-09T22:03:59.607 に答える
1

ああ!あなたがしたいeach_with_object。このような

def to_hierarchy stuff
  stuff.each_with_object({}) do |thing, h|
    path = thing.uri.split("/").drop(4)
    sub_h = h
    path.each do |segment|
      sub_h[segment] ||= {}
      sub_h = sub_h[segment]
    end
    sub_h.merge!(
        data: thing.data,
    )
  end
end
于 2013-09-09T22:06:44.347 に答える