【问题标题】:Ruby: How to write the atrribute values of an object from an array of objects to csvRuby:如何将对象的属性值从对象数组写入csv
【发布时间】:2013-09-12 15:18:56
【问题描述】:

需要知道如何将对象的属性值从对象数组写入 csv。

例如。

class Item
  attr_accessor :name, :weight, :price
end

def Item.create_item(name, weight, price)
  a = Item.new
  a.name = name
  a.weight = weight
  a.price = price
  return a
end

array_of_items = []

array_of_items << create_item(n1, w1, p1)
array_of_items << create_items(n2,w2,p2)
.....

我需要生成以下所需输出格式的 csv 文件

row0 - 名称、重量、价格

row1 - n1, w1, p1

第 2 行 - n2, w2, p2

等等

上述任何指示都会有所帮助。

编辑:

根据反馈尝试了以下。

class Item
  attr_accessor :name, :weight, :price

  def initialize(name, weight, price)
      @name, @weight, @price = name, weight, price
  end

  def to_s
    [@name, @weight, @price].join(', ')
  end
end

itemlist = []
itemlist << Item.new("Rice", 2, 40)
itemlist << Item.new("Wheat", 3, 80)

CSV.open("items.csv", "wb") do |csv|
 itemlist.each do |i|
  csv << i
 end
end

这会引发以下错误 - NoMethodError: 未定义的方法 `map' 为 Rice, 2, 40:Item 。

如果我检查 itemlist.class,那就是 Array; itemlist[0].class 是 Item - 这里没有惊喜。我认为您说上面定义的 to_s 实例方法应该在将内容添加到 CSV 时处理打印问题,但这似乎不起作用。

【问题讨论】:

    标签: ruby arrays object csv


    【解决方案1】:

    你可以这样做:

    require "csv"
    
    class Item
      attr_accessor :name, :weight, :price
    end
    
    def Item.create_item(name, weight, price)
      a = Item.new
      [a.name = name,a.weight = weight,a.price = price]
    end
    
    CSV.open("/home/kirti/ruby/csv/test.csv", "wb") do |csv|
      csv << ['name' , 'weight', 'price']
      csv << Item.create_item(:foo, 23, 11)
    end
    

    输出:

    name,weight,price
    foo,23,11
    

    【讨论】:

    • 谢谢,以上工作。请问我用的create_item方法定义和你用的有什么区别?
    • @joetom 在您的文件中,您返回了 Item 类的对象,这不是您要保存在 .csv 文件中的对象。您想保存 Item 类的对象的属性值。因此我写了[a.name = name,a.weight = weight,a.price = price]。希望能帮助到你。如果您还有其他问题,请解雇我..
    【解决方案2】:

    ruby 方法总是返回最后一个值。您的方法 Item.create_item 返回 a.price,因为这是最后一个值。

    要解决这个问题,您有两个选择。

    添加显式返回语句:

    def Item.create_item(name, weight, price)
      a = Item.new
      a.name = name
      a.weight = weight
      a.price = price
      return [name, weight, price]
    end
    

    使用一种叫做并行分配的东西

    def Item.create_item(name, weight, price)
      a = Item.new
      a.name, a.weight, a.price  = name, weight, price
    end
    

    第二个选项也将返回一个包含您想要的值的数组,因为它是方法的最后一行。

    Babai 的回答告诉您如何将值输出到 csv。

    编辑:

    在您的代码中,当您返回项目 a 时,它不知道如何在将其添加到 csv 时将其打印出来。解决的方法是定义 to_s 方法,该方法是在将内容添加到 csvs 或打印到屏幕时调用的方法。

    请注意,我还重写了函数 a 以使用实例变量和初始化函数。希望它不会增加太多混乱。

    class Item
      attr_accessor :name, :weight, :price
    
      def initialize(name, weight, price)
          @name, @weight, @price = name, weight, price
      end
    
      def to_s
        [@name, @weight, @price].join(', ')
      end
    
    end
    
    array_of_items = []
    array_of_items << Item.new('name_of_item', 'weight_of_item', 'price_of_item')
    

    评论后编辑:

    查看 CSV 模块的文档后,CSV 需要一个数组。有两种方法可以做到。

    要么:

    CSV.open("items.csv", "wb") do |csv|
      itemlist.each do |item|
        csv << [item.name, item.weight, item.price] 
        # item.name works because we added the attr_accessor
      end
    end
    

    或:

    class Item
      def to_array
        [@name, @weight, @price] 
      end
    end
    
    CSV.open("items.csv", "wb") do |csv|
      itemlist.each do |i|
        csv << i.to_array 
      end
    end
    

    【讨论】:

    • 感谢您的解释。如果 create_item 方法像 "return a" 那样返回 Item 对象,问题是什么。在尝试此操作并随后调用“csv
    • 嗯,首先你创建项目的方式有点奇怪。我在我的答案中添加了一件事,以阐明通常如何编写代码。
    • 我通过实例变量等尝试了正常的方法。但是在将 Item 添加到数组时会引发错误 - NoMethodError: undefined method 'map' for Rice, 2, 40:Item 。我看到您提到定义的 to_s 方法应该处理打印部分,但这似乎不起作用。请参阅原帖中的编辑。
    • 啊,csv真的要一个数组,所以我们必须创建一个to_array函数。请参阅我对此答案的编辑。
    猜你喜欢
    • 1970-01-01
    • 2011-05-27
    • 1970-01-01
    • 2022-12-03
    • 2016-01-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多