【问题标题】:converting a hash into array in ruby在ruby中将哈希转换为数组
【发布时间】:2018-04-19 15:30:29
【问题描述】:

我需要下一个哈希:

x = {
  params: {
    user_params1: { name: "stephen", dir: "2001", dir2: nil },
    user_params2: { name: "josh", dir: "jhon", dir2: nil }
}

像这样返回一个新的数组散列:

x = {
  params: {
    user_params1: ["stephen","201", ""],
    user_params2: ["josh","jhon",""]
}

【问题讨论】:

  • 第二件事是无效的。特别是这些部分:{"stephen","201", ""}{"josh","jhon",""}。而且,实际上,第一件事也不是(您似乎缺少一个右括号)。
  • 您遇到问题的代码是什么?你的代码有什么问题?您收到错误消息吗?错误信息是什么?你得到的结果不是你期望的结果吗?你期望什么结果,为什么,你得到的结果是什么,两者有什么不同?您正在观察的行为不是期望的行为吗?期望的行为是什么,为什么,观察到的行为是什么,它们有何不同?请提供minimal reproducible example
  • 您能否提供一个精确说明您希望发生的事情,包括任何和所有规则、这些规则的例外情况、极端情况、特殊情况、边界情况和边缘情况?您能否提供示例输入和输出来展示您期望发生的情况,无论是在正常情况下,还是在所有异常情况、极端情况、特殊情况、边界情况和边缘情况下?请同时确保提供minimal reproducible example
  • “我需要下一个散列来返回这样的数组的新散列”——你可以通过编写一个程序来做到这一点。如果您的程序有问题,请仔细阅读您正在使用的所有方法、类、模块和库的文档,为您的程序编写测试,用笔和纸跟踪执行,在调试器中单步执行,然后睡在上面,从头开始,再睡,然后然后只有这样将你的问题缩小到简洁、集中、简单、简短、可重复的minimal reproducible example 并询问具体的,在Stack Overflow 上关注的、狭窄的问题。

标签: ruby-on-rails ruby ruby-on-rails-4


【解决方案1】:

给定:

x = {
      params: {
        user_params1: { name: "stephen", dir: "2001", dir2: nil },
        user_params2: { name: "josh", dir: "jhon", dir2: nil }
      }
    }

试试:

x[:params] = x[:params].each_with_object({}) do |(k,v), returning|
  returning[k] = v.map{|k,v| v}
end

这将产生:

{:params=>{:user_params1=>["stephen", "2001", nil], :user_params2=>["josh", "jhon", nil]}}

如果您想要空字符串而不是 nils(如您的示例中所示),请执行以下操作:

x[:params] = x[:params].each_with_object({}) do |(k,v), returning|
  returning[k] = v.map{|k,v| v.to_s}
end

如果您不想修改x,则只需创建一个新的hash 并执行相同操作:

y ={}
y[:params] = x[:params].each_with_object({}) do |(k,v), returning|
  returning[k] = v.map{|k,v| v.to_s}
end

由于您没有对 v.map 中的 k 做任何事情,您可以只做 v.values.map(&:to_s) (从 Gerry 的回答中无耻地窃取) - 这更清洁,IMO,但会花费您一个额外的字符(!) - 最终得到:

y ={}
y[:params] = x[:params].each_with_object({}) do |(k,v), returning|
  returning[k] = v.values.map(&:to_s)
end

正如 Sebastian 指出的,这有语法糖:

y[:params] = x[:params].transform_values do |value|
  # Then use one of:
  #   hash.values.map { |value| value.nil? ? '' : value }
  #   hash.values.map { |value| value ? value : '' }
  #   hash.values.map { |value| value || '' }
  #   hash.values.map(&:to_s)      
end

有趣的是,如果您查看source code, 你会看到each_with_objecttranform_values 的机制非常相似:

def transform_values
  return enum_for(:transform_values) unless block_given?
  result = self.class.new
  each do |key, value|
    result[key] = yield(value)
  end
  result
end

你可以想象这个重写为:

def transform_values
  return enum_for(:transform_values) unless block_given?
  each_with_object(self.class.new) do |(key, value), result|
    result[key] = yield(value)
  end
end

从根本上说 (IMO),这几乎就是 Gerry 和我想出的。

在我看来这只猫皮肤很好。

【讨论】:

  • 有趣的方法比较,不错。
【解决方案2】:

您使用each_with_object(两次,以防您在顶层有多个一键);例如:

x.each_with_object({}) do |(k, v), result|
  result[k] = v.each_with_object({}) do |(k1, v1), result1|
    result1[k1] = v1.values.map(&:to_s)
  end
end

#=> {:params=>{:user_params1=>["stephen", "2001", ""], :user_params2=>["josh", "jhon", ""]}}

【讨论】:

    猜你喜欢
    • 2010-12-11
    • 1970-01-01
    • 2018-03-20
    • 2021-01-17
    • 1970-01-01
    • 1970-01-01
    • 2021-10-16
    • 2017-07-06
    • 1970-01-01
    相关资源
    最近更新 更多