代码之家  ›  专栏  ›  技术社区  ›  Galet

如何在rails的CSV字符串中添加新列

  •  0
  • Galet  · 技术社区  · 6 年前

    我想在CSV响应中添加新列并更新现有值。如何以更简单更好的方式进行以下转换?

    输入

    id,name,country
    1,John,US
    2,Jack,UK
    3,Sam,UK
    

    我使用以下方法来解析csv字符串并添加新列

    # Parse original CSV
    rows = CSV.parse(csv_string, headers: true).collect do |row|
      hash = row.to_hash
      # Merge additional data as a hash.
      hash.merge('email' => 'sample@gmail.com')
    end
    
    # Extract column names from first row of data
    column_names = rows.first.keys
    # Generate CSV after transformation of csv
    csv_response = CSV.generate do |csv|
      csv << column_names
      rows.each do |row|
        # Extract values for row of data
        csv << row.values_at(*column_names)
      end
    end
    

    我使用以下方法来解析csv并更新现有值

    name\u hash={“John”=>“Johnny”,“Jack”=>“Jackie”}

    分析原始CSV

    rows = CSV.parse(csv_string, headers: true).collect do |row|
      hash = row.to_hash
      hash['name'] = name_hash[hash['name']] if name_hash[hash['name']] != nil
      hash
    end
    
    # Extract column names from first row of data
    column_names = rows.first.keys
    # Generate CSV after transformation of csv
    csv_response = CSV.generate do |csv|
      csv << column_names
      rows.each do |row|
        # Extract values for row of data
        csv << row.values_at(*column_names)
      end
    end
    
    0 回复  |  直到 6 年前
        1
  •  1
  •   iGian    6 年前

    一个可能的选项是提供以下用于修改表的参考数据:

    name_hash = {"John" => "Johnny", "Jack" => "Jackie"}
    sample_email = {'email' => 'sample@gmail.com'}
    

    只需在行中存储转换为哈希的表:

    rows = CSV.parse(csv_string, headers: true).map(&:to_h)
    #=> [{"id"=>"1", "name"=>"John", "country"=>"US"}, {"id"=>"2", "name"=>"Jack", "country"=>"UK"}, {"id"=>"3", "name"=>"Sam", "country"=>"UK"}]
    


    然后根据引用数据修改哈希(我使用 Object#then 对于Ruby 2.6.1的别名 Object#yield_self 对于Ruby 2.5):
    rows.each { |h| h.merge!(sample_email).then {|h| h['name'] = name_hash[h['name']] if name_hash[h['name']] } }
    #=> [{"id"=>"1", "name"=>"Johnny", "country"=>"US", "email"=>"sample@gmail.com"}, {"id"=>"2", "name"=>"Jackie", "country"=>"UK", "email"=>"sample@gmail.com"}, {"id"=>"3", "name"=>"Sam", "country"=>"UK", "email"=>"sample@gmail.com"}]
    


    最后还原表:
    csv_response = CSV.generate(headers: rows.first.keys) { |csv| rows.map(&:values).each { |v| csv << v } }
    

    所以你现在有了:

    puts csv_response
    
    # id,name,country,email
    # 1,Johnny,US,sample@gmail.com
    # 2,Jackie,UK,sample@gmail.com
    # 3,Sam,UK,sample@gmail.com