请帮我处理我的Ruby脚本(ruby 2.0.0p481)

时间:2015-02-08 20:37:06

标签: ruby json

我正在编写一个ruby脚本来接受一个CSV输入文件。我想制作一个漂亮的JSON文件。我觉得我很亲密,但我似乎无法到达那里。我的原始项目是在JS中,但是需求已经改变,使其成为一个Ruby文件。

我的输入文件如下所示

商品ID,描述,价格,成本,price_type,quantity_on_hand,size_1_name,size_1_price,size_2_name,size_2_price,size_3_name,size_3_price

需要注意的一点是,CSV文件中的某些值可能会丢失,因为它不存在。

require 'csv'
require 'json'

def is_int(str)
  return !!(str =~ /^[-+]?[1-9]([0-9]*)?$/)
end

lines = CSV.open(ARGV[0],{:col_sep => ","}).readlines
# remove first entry of the lines array 
keys = lines.shift  

lines.each do |values|
     # convert the line into a hash and transform string into int
     #hash=Hash[keys.zip(values.map{|val| is_int(val) ? val.to_i : val}) ]
     hash = keys.zip(values.map{ val})
     # Write a file with the hash results
     File.open("#{hash['NAME']}.json", "w") do |f|
        f.write JSON.pretty_generate [hash]
     end
end

我想要的输出是

[
  {
    id: 111010,
    description: 'Coffee',
    price: 1.25,
    cost: 0.80,
    price_type: 'system',
    quantity_on_hand: 100000,
    modifiers: [
      {
        name: 'Small',
        price: -0.25
      },{
        name: 'Medium',
        price: 0.00
      },{
        name: 'Large',
        price: 0.30
      }
    ]

Ruby I使用的版本是2.0.0p481

Error was

usr/lib/ruby/2.0.0/csv.rb:1254:in `initialize': no implicit conversion of nil into String (TypeError)
    from /usr/lib/ruby/2.0.0/csv.rb:1254:in `open'
    from /usr/lib/ruby/2.0.0/csv.rb:1254:in `open'
    from stockimporter.rb:8:in `<main>'

1 个答案:

答案 0 :(得分:1)

csv.csv:

id,description,price,cost,price_type,quantity_on_hand,size_1_name,size_1_price,size_2_name,size_2_price,size_3_name,size_3_price
111010,Coffee,1.25,0.80,system,10000,Small,-0.25,Medium,0.00,Large,0.30
111011,Tea,1.00,0.50,system,100,Small,-0.10,Medium,0.00,Large,0.10
111012,MissingInfo,1.00,0.50,,100,,,Medium,,Large,0.10  

...

require 'csv'
require 'pp'
require 'json'

csv_options = {
  headers: true,  #skip first line of csv file
  converters: [:numeric]  #convert strings that look like integers or floats to integers or floats
}

results = []

CSV.foreach('csv.csv', csv_options) do |row|
  record = Hash[row.take(6)]

  modifiers = [
    {
      name: row["size_1_name"],
      price: row["size_1_price"]
    },
    {
      name: row["size_2_name"],
      price: row["size_2_price"],
    },
    {
      name: row["size_3_name"],
      price: row["size_3_price"]
    }
  ]

  record['modifiers'] = modifiers
  results << record
end

pp results


--output:--
[{"id"=>111010,
  "description"=>"Coffee",
  "price"=>1.25,
  "cost"=>0.8,
  "price_type"=>"system",
  "quantity_on_hand"=>10000,
  "modifiers"=>
   [{:name=>"Small", :price=>-0.25},
    {:name=>"Medium", :price=>0.0},
    {:name=>"Large", :price=>0.3}]},
 {"id"=>111011,
  "description"=>"Tea",
  "price"=>1.0,
  "cost"=>0.5,
  "price_type"=>"system",
  "quantity_on_hand"=>100,
  "modifiers"=>
   [{:name=>"Small", :price=>-0.1},
    {:name=>"Medium", :price=>0.0},
    {:name=>"Large", :price=>0.1}]},
 {"id"=>111012,
  "description"=>"MissingInfo",
  "price"=>1.0,
  "cost"=>0.5,
  "price_type"=>nil,
  "quantity_on_hand"=>100,
  "modifiers"=>
   [{:name=>nil, :price=>nil},
    {:name=>"Medium", :price=>nil},
    {:name=>"Large", :price=>0.1}]}]



json = JSON.pretty_generate(results)
puts json


--output:--
[
  {
    "id": 111010,
    "description": "Coffee",
    "price": 1.25,
    "cost": 0.8,
    "price_type": "system",
    "quantity_on_hand": 10000,
    "modifiers": [
      {
        "name": "Small",
        "price": -0.25
      },
      {
        "name": "Medium",
        "price": 0.0
      },
      {
        "name": "Large",
        "price": 0.3
      }
    ]
  },
  {
    "id": 111011,
    "description": "Tea",
    "price": 1.0,
    "cost": 0.5,
    "price_type": "system",
    "quantity_on_hand": 100,
    "modifiers": [
      {
        "name": "Small",
        "price": -0.1
      },
      {
        "name": "Medium",
        "price": 0.0
      },
      {
        "name": "Large",
        "price": 0.1
      }
    ]
  },
  {
    "id": 111012,
    "description": "MissingInfo",
    "price": 1.0,
    "cost": 0.5,
    "price_type": null,
    "quantity_on_hand": 100,
    "modifiers": [
      {
        "name": null,
        "price": null
      },
      {
        "name": "Medium",
        "price": null
      },
      {
        "name": "Large",
        "price": 0.1
      }
    ]
  }
]

你也可以这样做:

CSV.foreach('csv.csv', csv_options) do |row|
  record = Hash[row.take(6)]
  price_adjustments = row.drop(6)

  #             [["size_1_name", "Small"], ["size_1_price", -0.25]]
  #            |---------------------------------------------------|                          
  #                                      ^
  #                                      |
  modifiers = price_adjustments.each_slice(2).map do |size_price|
    size_price.first[0] = 'name'
    size_price.last[0] = 'price'
    Hash[size_price]
  end

  p modifiers  #e.g. [{"name"=>"Small", "price"=>-0.25}, {"name"=>"Medium", "price"=>0.0}, {"name"=>"Large", "price"=>0.3}]

  record['modifiers'] = modifiers
  results << record
end

pp results