簡體   English   中英

如何在循環中分配哈希數組?

[英]How to assign an array of Hashes in a loop?

我正在嘗試將ActiveRecord對象中的MySQL時間戳轉換為另一種時間戳格式。 我的方法采用ActiveRecord記錄數組,並返回帶有帶有時間戳記的字段和格式時間戳的哈希數組:

def convert_mysql_timestamps(records)
    ary = []
    hash = {}
    records.each_with_index do |record, i|
      record.attributes.each do |field, value|
        if time_columns.include?(field) and value then
          hash[field] = value.strftime("%Y-%m-%dT%H:%M:%S%z")
        else
          hash[field] = value
        end
      end
      ary[i] = {}
      ary[i] = hash
    end
    ary
  end

但是,當在ary[i] = hash分配中時,所有ary元素都設置為哈希。

有沒有更好的方法來轉換記錄的時間戳字段? (我不需要將記錄保存回數據庫。)而且,如何獲取數組來捕獲記錄的每個散列表示形式?

輸入:

[#<Vehicle id: 15001, approved_at: "2011-03-28 10:16:31", entry_date: "2011-03-28 10:16:31">, #<Vehicle id: 15002, approved_at: "2011-03-28 10:16:31", entry_date: "2011-03-28 10:16:31">]

所需的輸出:

[{"id"=>15001, "approved_at"=>"2011-03-28T10:16:31-0700", "entry_date"=>"2011-03-28T10:16:31-0700"}, {"id"=>15002, "approved_at"=>"2011-03-28T10:16:31-0700", "entry_date"=>"2011-03-28T10:16:31-0700"}]

問題是您要創建一個哈希:

def convert_mysql_timestamps(records)
  ary = []
  hash = {}
  #...

然后嘗試為每條記錄重復使用。 您可能希望為每個each_with_index迭代添加一個新的Hash:

  def convert_mysql_timestamps(records)
    ary = []
    records.each_with_index do |record, i|
      hash = { }
      record.attributes.each do |field, value|
        #...
      end
      ary[i] = hash
    end
  end

您可以為此使用map當您要采用一種格式的數組並以另一種格式生成相同大小的數組時,這始終是一個不錯的選擇。 這是如何做:

def convert_mysql_timestamps(records)
  records.map do |record|
    Hash[records.attributes.map{|k, v| [k, convert_mysql_timestamp(v)] }]
  end
end

def convert_mysql_timestamp(field, value)
  return value unless time_columns.include?(field) && value
  value.strftime("%Y-%m-%dT%H:%M:%S%z")
end

它的工作原理如下:

  • Hash[array_of_pairs]將鍵-值對數組(如[["foo", 2], ["bar", 3], ...] )轉換為類似{"foo" => 2, "bar" => 3, ...}

  • map為集合中的每個項目調用其塊,並將該塊的每個返回值收集到一個新數組中,並返回該數組。 Hash[...]內部的attributes.map創建鍵-值對的數組,而外部records.map將所有散列收集到返回的數組中。

我建議您閱讀Enumerable中的方法,因為其中包含map類的整潔事物。 您會發現幾乎不需要在循環中使用索引,盡管如果您來自另一種語言,並且for每個地方都有for循環,那么就很難改掉!

我不確定您的time_columns是什么,但是假設它們是Time類,則可以簡化諸如value.is_a?(Time)類的部分。

def convert_mysql_timestamps(records)

 records.collect do |record|
   # assuming records are from a Rails model, I am using #attributes 
   # to loop through all fields in a record 
                    # then inject values in this hash -> ({}), 
                    # which is in the block, named attributes
   record.attributes.inject({}) do |attributes, (column_name, value)|
     # if it is Time, convert it to iso8601 (slightly different from your format, 
     # but if this is also acceptable, your code can be simpler)
     attributes[column_name] = (value.is_a?(Time) ? value.iso8601 : value)
     attributes
   end
 end

end

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM