【问题标题】:How do I generate constants to access Ruby array elements?如何生成常量来访问 Ruby 数组元素?
【发布时间】:2012-03-30 09:16:29
【问题描述】:

我使用一个数组来存储字段值。为了轻松添加和访问元素,我使用常量作为元素标识符。

到目前为止,我是这样手动完成的:

stages = ["lidnummer","aardf","prest","dt_prest","aantal","bedrag","verstrekker","foutcode"]
values = ["it","can","be","anything",0,5.3,nil,88] 
LIDNUMMER,AARDF,PREST,DT_PREST,AANTAL,BEDRAG,VERSTREKKER,FOUTCODE = 0,1,2,3,1,5,6,7
p values[AARDF] => "can"

现在我已经像这样自动化了:

stages = ["lidnummer","aardf","prest","dt_prest","aantal","bedrag","verstrekker","foutcode"]
values = ["it","can","be","anything",0,5.3,nil,88] 
stages.each do |c|
  eval "#{c.upcase} = #{stages.index(c)}"
end
p values[AARDF] => "can"

但我想有更好的 Ruby 方式来做到这一点,也许没有 eval,有什么建议吗?

【问题讨论】:

  • 红宝石中的幻数是Symbols,所以试着用它们来做吧。
  • 编辑了 values 数组以更清楚我需要什么

标签: ruby arrays constants eval


【解决方案1】:

如果你坚持按照你描述的方式而不是使用哈希,这是我能想到的最简单的方法:

stages.zip(values) { |stage, value| Object.const_set(stage.upcase, value) }
values[BEDRAG] #=> 5

我个人只是建立一个哈希,但你比我更了解你的需求:

Hash[stages.map(&:upcase).zip(values)]
#=> {"LIDNUMMER"=>0, "AARDF"=>1, "PREST"=>2, "DT_PREST"=>3, "AANTAL"=>4, "BEDRAG"=>5, "VERSTREKKER"=>6, "FOUTCODE"=>7}

【讨论】:

  • @michael values[BEDRAG] 对你意味着什么......我总是可以直接访问 BEDRAG
  • @SandipRansing 他可以const_set 其他东西的价值,我只是想向 OP 展示一种更惯用的方式来做他想做的事,这就是他所要求的。
  • @MichaelKohl ah..okk.. 使用Hash[something]inject({}) 有什么特别的区别
  • @SandipRansing 它们是完全不同的东西。 Hash[] 接受一个包含两个元素数组的数组并将其转换为哈希,而 inject 是编程中通常所说的折叠:en.wikipedia.org/wiki/Fold_(higher-order_function) 当然,您可以使用注入来构建哈希,但如果您已经有2 个数组 zip + Hash[] 更容易。
【解决方案2】:

是的,使用 HashSymbols。

stages = {:aardf => "aardf", :prest => "prest", ...}
stages[:aardf]

对于旧版,请使用

AARDF = :aardf

stages[AARDF]

仍然有效。

【讨论】:

  • 我已经在像这样的其他情况下使用哈希
    stages = {:aardf => "aardf", :prest => "prest"}
    p stages[:aardf]
    但有时数组更好..在这种情况下,我需要确保没有添加任何元素并且元素始终具有相同的顺序
  • Tass,我编辑了我的问题以更好地解释我需要什么,你会发现这里的哈希不能像平滑阶段 = {:aardf => 1, :prest => 2}值 = [0,1,2,3,4,5,6,7] p 值[stages[:aardf]]
  • 然后使用ruby 1.9和Hash,元素在那里排序。
【解决方案3】:

您可能会感兴趣的其他方式 -

stages = ["lidnummer","aardf","prest","dt_prest","aantal","bedrag","verstrekker","foutcode"]
    values = [0,1,2,3,4,5,6,7]

stages = stages.zip(values).inject({}) {|h, (k,v)| h[k.upcase]=v;h}
=> {"LIDNUMMER"=>0, "FOUTCODE"=>7, "BEDRAG"=>5, "VERSTREKKER"=>6, "AANTAL"=>4, "PREST"=>2, "AARDF"=>1, "DT_PREST"=>3}


p stages['AARDF'] #=> 1

【讨论】:

  • 谢谢,但这还不够,实际上有两个数组,一个带有字段名,一个带有值,我将编辑我的问题以更好地显示这一点
  • 更简单:Hash[stages.map(&:upcase).zip(values)] 用于更新问题或Hash[stages.map(&:upcase).zip(stages)] 用于原始问题。
【解决方案4】:

谢谢大家,我学到了很多。 Michael 的答案最接近但不正确(值数组可以包含任何内容,通常不是元素的顺序)。 我设法结合了这里介绍的不同技术,并提出了以下建议。

stages = ["lidnummer","aardf","prest","dt_prest","aantal","bedrag","verstrekker","foutcode"]
values = ["it","can","be","anything",0,5.3,nil,88]
stages.each_with_index{|c,i|Object::const_set(c.upcase, i)}
p values[AARDF] => "it"
p values[BEDRAG] => 5.3

如果我使用哈希,它对错误更敏感,我会结束使用

p values[hash["AARDF"]]

没有那么流畅

【讨论】:

  • 请不要添加答案,除非它是您最初发布的问题的选定解决方案。相反,请修改您的原始问题并在上面附加您的信息。这使搜索的人可以轻松找到您的解决方案,而不是强迫他们搜索整个集合。
  • 好吧,迈克尔是唯一一个靠近我的人,我编辑了他的答案以解决一个错误,但即使在更正之后我认为我的解决方案更短..,所以请原谅我接受我自己的答案最好的解决方案,除非有人想出更简单或更短的东西。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多