首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何组合和打印嵌套对象结构的值?

如何组合和打印嵌套对象结构的值?
EN

Stack Overflow用户
提问于 2021-09-24 09:45:48
回答 2查看 80关注 0票数 2

我有一个散列数组,每个散列都需要打印在同一行上。

代码语言:javascript
复制
init_cards_j = [
  { init1: [{ num: 6, head: 1 }, { num: 10, head: 1 }] },
  { init2: [{ num: 53, head: 1 }, { num: 60, head: 1 }] },
  { init3: [{ num: 77, head: 5 }] },
  { init4: [{ num: 89, head: 1 }] }
]

我希望它看起来像这样:

代码语言:javascript
复制
Card 6: 1 head / Card 10: 1 head
Card 53: 1 head / Card 60: 1 head
Card 77: 5 head
Card 89: 1 haed

我尝试了如下:

代码语言:javascript
复制
init_cards_j.each_index do |index|
  init_cards_j[index].values[0].each do |pair|
    init_cards_j[index].each do |key, value|
      value.each do |pair|
        puts "Card #{pair[:num]}: #{pair[:head]} kettle head. / "
      end
    end
  end
end

将数据输出为:

代码语言:javascript
复制
Card 6: 1 kettle head. / 
Card 10: 1 kettle head. / 
Card 6: 1 kettle head. / 
Card 10: 1 kettle head. / 
Card 53: 1 kettle head. / 
Card 60: 1 kettle head. / 
Card 53: 1 kettle head. / 
Card 60: 1 kettle head. / 
Card 77: 5 kettle head. / 
Card 89: 1 kettle head. / 

很抱歉,我的数组是如此嵌套,因为我需要按num对每个散列排序,我将它们放在一个数组中。

提前感谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-09-24 10:23:56

您可以通过init_cards_j通过each迭代散列,并为每个哈希调用each_value遍历其值。然后,不必立即打印每一张卡,您可以通过mapjoin生成中间数组--使用分隔符字符串生成结果:

代码语言:javascript
复制
init_cards_j.each do |hash|
  hash.each_value do |values|
    puts values.map { |c| "Card #{c[:num]}: #{c[:head]} head" }.join(' / ')
  end
end

但是,更容易将散列数组转换为单个散列:(假设它们的键是唯一的)

代码语言:javascript
复制
cards = {
  init1: [{ num: 6, head: 1 }, { num: 10, head: 1 }],
  init2: [{ num: 53, head: 1 }, { num: 60, head: 1 }],
  init3: [{ num: 77, head: 5 }],
  init4: [{ num: 89, head: 1 }]
}

如果必须保留给定的结构,则可以动态转换它:

代码语言:javascript
复制
cards = init_cards_j.inject(&:merge)

这使得循环变得更简单:

代码语言:javascript
复制
cards.each_value do |values|
  puts values.map { |c| "Card #{c[:num]}: #{c[:head]} head" }.join(' / ')
end

为了进一步细化输出,您可以将循环从卡片描述中分离出来,将后者提取到一个方法中:

代码语言:javascript
复制
def description(card)
  "Card #{card[:num]}: #{card[:head]} head"
end

init_cards_j.each do |hash|
  hash.each_value do |values|
    puts values.map { |card| description(card) }.join(' / ')
  end
end

现在可以通过编辑description方法向输出字符串添加更多的逻辑,例如:

代码语言:javascript
复制
def description(card)
  if card[:head] == 1
    "Card #{card[:num]}: #{card[:head]} head"
  else
    "Card #{card[:num]}: #{card[:head]} heads"
  end
end

上面的内容可以写得更紧凑,但我将把优化留给您。

票数 2
EN

Stack Overflow用户

发布于 2021-09-24 21:35:09

我推荐@Stefan的第一个答案,但这里有另一个方法可以实现同样的结果。

我们可以从helper方法开始,当然可以单独测试该方法:

代码语言:javascript
复制
def print_num_and_head(g)
  print "Card %d: %d head" % g.values_at(:num, :head)
end

如果

代码语言:javascript
复制
g = {:num=>6, :head=>1})

然后

代码语言:javascript
复制
print_num_and_head(g)

显示

代码语言:javascript
复制
Card 6: 1 head

没有线终结者。

然后我们可以写:

代码语言:javascript
复制
init_cards_j.each do |h|
  _, (g, *arr) = h.flatten
  print_num_and_head(g)
  arr.each do |g|
    print ' / '
    print_num_and_head(g)
  end
  puts   
end

版画

代码语言:javascript
复制
Card 6: 1 head / Card 10: 1 head
Card 53: 1 head / Card 60: 1 head
Card 77: 5 head
Card 89: 1 head

在这里,我使用了Ruby的强大的array#decomposition (也就是数组消歧)语法来获得优势:

如果

代码语言:javascript
复制
h = { init1: [{ num: 6, head: 1 }, { num: 10, head: 1 }] }

然后

代码语言:javascript
复制
_, (g, *arr) = h.flatten
  #=> [:init1, [{:num=>6, :head=>1}, {:num=>10, :head=>1}]]
_ #=> :init1
g #=> {:num=>6, :head=>1}
arr
  #=> [{:num=>10, :head=>1}]

当块计算中没有使用块变量时,我使用了用下划线表示块变量的通用约定。

有关更全面的解释数组分解,请参见这篇文章

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69312912

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档