简体   繁体   English

Ruby 如何格式化嵌套哈希

[英]Ruby how to format nested hash

I have two queries I am running and iterating over both and my final hash is seen below.我有两个查询我正在运行并迭代这两个查询,我的最终哈希如下所示。 But, I want to have format on how the data is being stored in the hash that I'm creating or format it after I'm done creating it.但是,我想对数据如何存储在我创建的哈希中进行格式化,或者在创建完成后对其进行格式化。 But I am not sure how to achieve the desired format where the names fall under the same id as show below但我不确定如何实现所需的格式,其中names与下面显示的id相同

desired format of example data:示例数据的所需格式:

[
    {
        id: 1,
        accepted: false,
        trans: 10234
        names: [
            { name: "Joe", amount: "$1,698.00" },
            { name: "Smith", amount: "$674.24" },
        ]
    },
    {
        id: 2,
        accepted: true,
        trans: 10234,
        names: [
            { name: "Joe", amount: "$1,698.00" },
            { name: "Smith", amount: "$674.24" },
        ]
    }
]

current format I have我的当前格式

[
    {
               :id => 1,
               :accepted => false,
               :trans => 8,
               :name => "Smith",
               :amount => 36.0
    },
    {
               :id => 1,
               :amount => false,
               :trans => 8,
               :name => "Joe",
               :amount => 6.0
    },
    {
               :id => 3,
               :accepted => false,
               :trans => 8,
               :name => "Tom",
               :amount => 34.0
    },
     {
               :id => 3,
               :accepted => false,
               :trans=> 8,
               :name => "Martha",
               :amount => 4.0
    }
], 
[
    {
               :id => 2,
               :accepted => true,
               :trans => 7,
               :name => "Bob",
               :amount => 35.0
    },
     {
                :id => 2,
                :accepted => true,
                :trans => 7,
                :name => "John",
                :amount => 5.0
    }
]

logic for creating hash创建哈希的逻辑

imports = ListImports.limit(20).order(created_at: :DESC)
groups = imports.map{|import| ListImportGroup.where(list_import_id: import.id)}
pub_hash_true = []
pub_hash_false = []
hash = []
imports.map do |import|
  hash << {
     id: import.id,
     trans: import.trans,
     accepted: import.amount
  }
end
  hash.each do |import|
    groups.flatten.each do |group|
      accepted = import[:accepted]
      num_transactions = import[:trans]
      if accepted == false
        pub_hash_false << {id: import[:id], accepted: accepted, trans: num_transactions, name: group.name, amount: group.amount}
      else
        pub_hash_true << {id: import[:id], accepted: accepted, trans: num_transactions, name: group.name, amount: group.amount}
      end
    end
  end
# Note: You didn't specify what is the association between `ListImport` and `ListImportGroup`.
# However, I'm fairly sure you could be fetching this data via a JOIN query like below,
# rather than making up to 20 additional database calls to fetch the associated records.

imports = ListImports.limit(20).order(created_at: :DESC).includes(:list_import_group)

result = imports.map do |import|
  {
    id: import.id,
    trans: import.trans,
    accepted: import.amount,
    names: import.list_import_groups.pluck(:name, :amount)
  }
end

And if you do actually need to filter for imports where accepted is true or false , you could do something like this instead of building separate arrays manually:如果您确实需要过滤acceptedtruefalse导入,您可以执行以下操作,而不是手动构建单独的数组:

accepted_imports = result.select { |import| import[:accepted] }
# and
rejected_imports = result.reject { |import| import[:accepted] }

# or even:
accepted_imports, rejected_imports = result.partition { |import| import[:accepted] }

You didn't specify the exact correspondence between the desired and current formats.您没有指定所需格式和当前格式之间的确切对应关系。 But I assume但我假设

  • For the entries with the same id , the values of accepted and trans are identical.对于具有相同id的条目, acceptedtrans的值是相同的。
  • the desired amount for Joe in the current format is identical in the corresponding amount in the desired amount .乔在当前格式所需的量在以期望相应的量相同。 (In your example, the former is 6.0 whereas the latter is "$1,698.00" , which does not make sense.) (在您的示例中,前者是6.0而后者是"$1,698.00" ,这是没有意义的。)

Then, the following would do the conversion.然后,以下将进行转换。 The array ahout is in the desired format.数组ahout所需的格式。

 # Let us assume "a1" is the original array in the "current format"
hout = {}
a1.flatten.map{|h|
   h.slice(*(%i(id trans name amount accepted))).values
}.each{ |a|
  hout[a[0]] = {id: a[0], accepted: a[4], trans: a[1], names: []} if !hout.key? a[0]
  hout[a[0]][:names].push(
    {name: a[2], amount: "$"+helper.number_with_precision(a[3], precision: 2, delimiter: ',')}
  )
}

ahout = hout.values

You may want to sort ahout , if you like.如果您愿意,您可能想对ahout进行排序。

Note that I am assuming you are using Rails 5+.请注意,我假设您使用的是 Rails 5+。 Otherwise, the method helper may not work.否则,方法helper可能无法工作。 In that case, you can use sprintf or whatever formatting method.在这种情况下,您可以使用sprintf或任何格式化方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM