【问题标题】:How do I format an array of objects with ruby?如何使用 ruby​​ 格式化对象数组?
【发布时间】:2018-04-24 20:12:45
【问题描述】:

我对如何格式化这个对象数组有点迷茫。

初始数组:

cars = [{model: 'nissan', type: 'wingroad'},{model: 'nissan', type: 'sunny'},{model: 'nissan', type: 'terrano'},{model: 'toyota', type: 'hilux'}]

预期输出:

formatted_cars = [{name: 'nissan', value: ['wingroad', 'sunny', 'terrano']}, {name: 'toyota', value: ['hilux']

我是否会映射结果并应用注入,然后对该格式化数组应用一些巧妙的合并技术。或者还有其他方法可以解决吗?

我是 ruby​​ 新手,希望得到任何帮助,谢谢 :)

【问题讨论】:

标签: ruby-on-rails ruby


【解决方案1】:

有很多方法可以做到这一点。这是一个;

cars = [
  {model: 'nissan', type: 'wingroad'},
  {model: 'nissan', type: 'sunny'},
  {model: 'nissan', type: 'terrano'},
  {model: 'toyota', type: 'hilux'}
]

cars
  .group_by { |car| car[:model] }
  .map { |model, cars| {name: model, value: cars.map { |car| car[:type] }} }

...但是,您为什么要从这种奇怪的数据格式开始,并打算以另一种奇怪的数据格式结束呢? (所谓“奇数”,基本上是指依靠数组的哈希数组来存储数据。)

可能有一个很好的理由(例如,与第 3 方 API 集成),但除此之外,我建议以某种方式使其更加面向对象并使用类来定义汽车。例如,可能是这样的:

# e.g. Nissan
class CarMake
  attr_reader :name, :models
  def initialize(name)
    @name = name
    @models = []
  end

  def add_model(name)
    model = CarModel.new(name)
    @models << model
    model.make = self
  end
end

# e.g. WingRoad
class CarModel
  attr_reader :name
  attr_accessor :make
  def initialize(name)
    @name = name
  end
end

# Assuming we still need to start with this data structure!
cars = [
  {model: 'nissan', type: 'wingroad'},
  {model: 'nissan', type: 'sunny'},
  {model: 'nissan', type: 'terrano'},
  {model: 'toyota', type: 'hilux'}
]

car_makes = {}
cars.each do |car|
  car_makes[car[:model]] ||= CarMake.new(car[:model])
  car_makes[car[:model]].add_model(car[:type])
end

这只是组织代码的众多可能方式之一,虽然起初理解起来可能有点复杂,但生成的数据结构更有用:

car_makes
=> {"nissan"=>
  #<CarMake:0x00007ff2ee44ad20
   @models=
    [#<CarModel:0x00007ff2ee44aca8 @make=#<CarMake:0x00007ff2ee44ad20 ...>, @name="wingroad">,
     #<CarModel:0x00007ff2ee44ac80 @make=#<CarMake:0x00007ff2ee44ad20 ...>, @name="sunny">,
     #<CarModel:0x00007ff2ee44ac58 @make=#<CarMake:0x00007ff2ee44ad20 ...>, @name="terrano">],
   @name="nissan">,
 "toyota"=>#<CarMake:0x00007ff2ee44ac30 @models=[#<CarModel:0x00007ff2ee44ab68 @make=#<CarMake:0x00007ff2ee44ac30 ...>, @name="hilux">], @name="toyota">}

car_makes['nissan'].models
=> [#<CarModel:0x00007ff2ee44aca8 @make=#<CarMake:0x00007ff2ee44ad20 @models=[...], @name="nissan">, @name="wingroad">,
 #<CarModel:0x00007ff2ee44ac80 @make=#<CarMake:0x00007ff2ee44ad20 @models=[...], @name="nissan">, @name="sunny">,
 #<CarModel:0x00007ff2ee44ac58 @make=#<CarMake:0x00007ff2ee44ad20 @models=[...], @name="nissan">, @name="terrano">]

car_makes['nissan'].models.first
=> #<CarModel:0x00007ff2ee44aca8
 @make=
  #<CarMake:0x00007ff2ee44ad20
   @models=
    [#<CarModel:0x00007ff2ee44aca8 ...>,
     #<CarModel:0x00007ff2ee44ac80 @make=#<CarMake:0x00007ff2ee44ad20 ...>, @name="sunny">,
     #<CarModel:0x00007ff2ee44ac58 @make=#<CarMake:0x00007ff2ee44ad20 ...>, @name="terrano">],
   @name="nissan">,
 @name="wingroad">

car_makes['nissan'].models.first.make
=> #<CarMake:0x00007ff2ee44ad20
 @models=
  [#<CarModel:0x00007ff2ee44aca8 @make=#<CarMake:0x00007ff2ee44ad20 ...>, @name="wingroad">,
   #<CarModel:0x00007ff2ee44ac80 @make=#<CarMake:0x00007ff2ee44ad20 ...>, @name="sunny">,
   #<CarModel:0x00007ff2ee44ac58 @make=#<CarMake:0x00007ff2ee44ad20 ...>, @name="terrano">],
 @name="nissan">

...等等。我们现在有了一个结构化的数据,而不是随意的(并且命名错误!)数组和哈希的混合,操作起来很麻烦。

【讨论】:

  • 感谢您的回答,是的,基本上数据类型必须是奇数,因为 formatted_cars 数组用于填充反应形式的选择字段。 :)
  • @John 如果他已经回答了你的问题,请考虑接受他的回答,左上角有一个tic,你需要点击,点击那个按钮后,它会变成绿色。
  • @John 我仍然建议使用像上面这样结构良好的模型,并生成必要的“React JSON”格式作为单独的方法。如果这是一个 Rails 应用程序,您可以通过标准序列化程序来执行此操作;或者如果我们在普通的 ruby​​ 对象中执行此操作,那么:class CarMake; def to_json; {name: name, value: models.map(&amp;:name)}; end; end ... 虽然我的观点仍然认为您在 model 之间有一个相当混乱的命名约定(应该是“make”!), type(应该是“型号”)和value(应该是“品牌”)。
【解决方案2】:
cars = [{model: 'nissan', type: 'wingroad'},
        {model: 'nissan', type: 'sunny'},
        {model: 'nissan', type: 'terrano'},
        {model: 'toyota', type: 'hilux'}]

cars.each_with_object({}) { |g,h| (h[g[:model]] ||= []) << g[:type] }.
     map { |k,v| { model:k, type:v } }
  #=> [{:model=>"nissan", :type=>["wingroad", "sunny", "terrano"]},
  #    {:model=>"toyota", :type=>["hilux"]}]

注意

cars.each_with_object({}) { |g,h| (h[g[:model]] ||= []) << g[:type] }
  #=> {"nissan"=>["wingroad", "sunny", "terrano"], "toyota"=>["hilux"]}

【讨论】:

    【解决方案3】:

    是的,有,如下:

    cars.group_by{|h| h[:model]}.transform_values{|v| v.map{|h| h[:type]}}
    #=> {"nissan"=>["wingroad", "sunny", "terrano"], "toyota"=>["hilux"]}
    

    【讨论】:

    • 请将此作为完整的答案,而不仅仅是没有解释的代码答案。
    • 感谢您的尝试,但没有以正确的格式返回答案,它应该嵌套在数组中。 [{name: 'nissan', value: ['wingroad', 'sunny', 'terrano']}, {name: 'toyota', value: ['hilux']}]
    猜你喜欢
    • 2020-01-07
    • 1970-01-01
    • 2020-10-19
    • 2015-01-18
    • 1970-01-01
    • 2023-03-08
    • 2019-10-14
    • 1970-01-01
    相关资源
    最近更新 更多