每个3个值的数据集的Ruby解决方案

时间:2013-04-15 13:10:17

标签: ruby arrays hash

所以我没有太多Ruby知识,但需要处理一个简单的脚本。我会试着详细解释我的困境,但如果你还需要澄清,请告诉我。

我的脚本每组包含3个数字。比方说,我们为每个人提供这三条信息:Age, Size, and Score。所以,我需要有一种方法来评估一个人是否存在某个年龄和大小。如果是的话,那么我想输出那个人的分数。

我知道跟踪此信息的唯一方法是创建3 separate arrays,每个information包含一个testarray = [ [27, 8, 92], [52, 12, 84] ] 。我可以检查年龄是否包含在一个数组中,如果是,我可以找到它的索引(每个类别中的每个值都是唯一的 - 所以没有“年龄”,“尺寸,“或”得分“将重复出现)。然后,我可以检查size数组中相同索引处的值是否与指定的大小匹配。如果是这样,我可以在同一索引处输出在第三个数组中找到的分数。我不希望这样做,而是将每个人的年龄大小得分保持在一起。

所以,我在数组中尝试了这样的数组:

subarray

然而,问题在于我不确定如何访问这些子数组中的值。所以我知道我可以使用像testarray.include一样的东西(27)来检查主阵列中是否存在27,但我如何检查27和8是否是testarray子阵列中的前两个值,如果是,然后输出testarrayb = [ { :age => 27, :size => 8, :score => 92 }, { :age => 52, :size => 12, :score => 84 } ] 的第三个值,92。

然后我尝试了一系列哈希,如下所示:

testarrayb[0][:score]

我知道我可以使用testarrayb[:age].include?(value)获得92但是我怎样才能首先检查数组是否包含具有指定年龄和大小的散列,如果是,则输出该散列的分数?类似于{{1}}的东西,其中检查每个散列的年龄,然后检查相同散列的大小。如果两者都匹配指定的值,则输出该哈希的分数。

如果有人能指出我正确的方向,我将非常感激。如果您推荐这种技术,请随意展示更高效和完全不同的技术。谢谢你的时间!

6 个答案:

答案 0 :(得分:3)

为什么不创建一个简单的类来表示您的数据,例如使用Struct。然后提供一些类方法来处理过滤。

Entry = Struct.new(:age, :size, :score) do
  # Holds the data (example)
  def self.entries; @entries ||= [] end

  # Example filtering method
  def self.score_by_age_and_size(age, size)
    entry = entries.find { |e| e.age == age && e.size == size }
    entry.score if entry
  end
end

# Add some entries
Entry.entries << Entry.new(27, 8, 92)
Entry.entries << Entry.new(52, 13, 90)

# Get score
Entry.score_by_age_and_size(27, 8) # => 92
Entry.score_by_age_and_size(27, 34) # => nil

答案 1 :(得分:2)

这将返回满足条件的哈希数组,然后在返回的哈希数组中指定第一个哈希的分数。

# return an array of hashes that satisfy the conditions
array_of_hashes = testarrayb.select { |h| h[:age] == 27 && h[:size] == 8 }

# assign the score
score = array_of_hashes[0][:score]
编辑:你可能想把它放在一个方法

# use an instance variable to reference the initial array defined outside this method
@testarrayb = [{:age=>27, :size=>8, :score=>92}, {:age=>52, :size=>12, :score=>84}]

def find_person(age, size)
  array_of_hashes = @testarrayb.select { |h| h[:age] == age && h[:size] == size }

  # since values in each column are unique we can assume array size of 0 or 1
  # return false if not found otherwise return the score
  !array_of_hashes.empty? && array_of_hashes[0][:score]
end

并将其称为:

find_person 27, 8
# => 92 

find_person 27, 7
# => false

答案 2 :(得分:1)

散列哈希是否可以帮到你?

testhash = {27 => {8 => 92}, 52 => {12 => 84}}
p testhash             # {27=>{8=>92}, 52=>{12=>84}}
p testhash[27][8]      # 92
p testhash[27][42]     # nil
testhash[27][42] = 99
p testhash             # {27=>{8=>92, 42=>99}, 52=>{12=>84}}
p testhash[27][42]     # 99

只要年龄/大小对是唯一的,这应该非常有效。

答案 3 :(得分:1)

从我的要求中可以看出来(“我需要一种方法来评估一个人是否存在某个年龄和大小”“我怎样才能先检查一下数组包含具有指定年龄和大小“”的哈希,您总是通过他们的年龄和大小对来识别一个人,并且您希望根据该对作为关键字来引用他们的分数。由于Ruby允许任何类型的Object作为Hashes中的键(或值),我们可以直接翻译它:

# `scores` hash is structured { [age, size] => score, ... }
scores = {[27, 8] => 92, [52, 12] => 84}

您可以询问是否存在具有特定年龄和大小的人:

scores.include?([27, 8])  # => true
scores.include?([27, 7])  # => false
scores.include?([28, 8])  # => false
scores.include?([52, 12]) # => true

你可以为一个人分配一个新的分数(同样,由年龄/大小对确定):

scores[[52, 12]] = 97
scores                    # => {[27, 8]=>92, [52, 12]=>97}

当然,既然您想要访问该值,那么您可以随时在nil之后测试:

score = scores[[27, 8]]   # `score` is now `92`
if !score.nil?
  # Do something with `score`
end

我更喜欢使用数组来表示一对,但另一种选择是使用哈希,这样您就可以为元素命名,而不用担心顺序:

scores = {{:age => 27, :size => 8} => 92, {:age => 52, :size => 12} => 84}
scores[{:size => 8, :age => 27}] # => 92

答案 4 :(得分:0)

你可能会做这样的事情:

[
  { age: 27, size: 8,  score: 92 },
  { age: 52, size: 12, score: 84 }
].map { |e| e[:age] == 27 && e[:size] == 8 ? e[:score] : nil }.compact

map会返回一个新的array,其中包含该块的结果(如果条件匹配,则为e[:score];如果不匹配则为nil。{{1}然后会删除生成的compact中不需要的nil

然而,这种行为听起来很适合它自己的类,因为我刚刚展示的内容包含很多硬编码的东西(尤其是选择条目的条件),这很糟糕。也许试着找出一个很好的课程?

答案 5 :(得分:0)

def person_score (*input)
    testarray = [
    [27, 8, 92],
    [52, 12, 84]
    ]
        testarray.each_with_object("") do|i,mem| 
            h = Hash[*([:age,:size,:score].zip(i).flatten)]
            (h.values.first(2) == input) ? (return h[:score]) : ( mem.replace("age and size not matched"))
        end
end

p person_score(27,12)  #=> "age and size not matched" 
p person_score(27,8)   #=> 92
p person_score(52,44)  #=> "age and size not matched"
p person_score(52,12)  #=> 84