Ruby如何格式化嵌套哈希
Posted
技术标签:
【中文标题】Ruby如何格式化嵌套哈希【英文标题】:Ruby how to format nested hash 【发布时间】:2021-12-22 08:50:47 【问题描述】:我有两个查询正在运行和迭代,我的最终哈希如下所示。但是,我想对数据如何存储在我正在创建的散列中或在我完成创建后格式化它进行格式化。但我不确定如何实现所需的格式,其中names
属于相同的id
,如下所示
示例数据的所需格式:
[
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" ,
]
]
我目前的格式
[
: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
]
创建哈希的逻辑
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
【问题讨论】:
你是如何生成最终结果的?改变世代可能比事后重新格式化更有意义 @SaraFuerst 我正在迭代两组数据并以这种方式创建哈希。我更新了我的问题以包含逻辑 什么是groups
?您没有显示变量的来源。
为什么需要pub_hash_true
和pub_hash_false
?您的问题最初不是关于将数据分成“真/假”组,并且您没有显示是否/如何使用这些变量。
@TomLord 它在被控制器调用时作为一个哈希返回。我更新了我的问题,以显示组的来源。这是结果查询。 pub_hash_true
和 ``` pub_hash_false``` 是分开接受的:真/假值
【参考方案1】:
# 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
如果您确实需要过滤 accepted
是 true
或 false
的导入,您可以执行以下操作,而不是手动构建单独的数组:
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]
【讨论】:
【参考方案2】:您没有指定 desired 和 current 格式之间的确切对应关系。 但我认为
对于具有相同id
的条目,accepted
和trans
的值是相同的。
当前格式中 Joe 的所需金额与 所需金额 中的相应金额相同。 (在您的示例中,前者是6.0
,而后者是"$1,698.00"
,这没有意义。)
然后,以下将进行转换。数组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
如果您愿意,可以对ahout
进行排序。
请注意,我假设您使用的是 Rails 5+。否则,helper
方法可能不起作用。在这种情况下,您可以使用sprintf
或任何格式化方法。
【讨论】:
以上是关于Ruby如何格式化嵌套哈希的主要内容,如果未能解决你的问题,请参考以下文章
在Ruby中将嵌套哈希键从CamelCase转换为snake_case