我有一个哈希数组:
@candidates = [
{
id: 15,
years_of_experience: 4,
github_points: 293,
languages: ['C', 'Ruby', 'Python', 'Clojure'],
age: 26
},
{
id: 7,
years_of_experience: 1,
github_points: 145,
languages: ['JavaScript', 'Ruby', 'Go', 'Erlang'],
age: 19
},
{
id: 9,
years_of_experience: 6,
github_points: 435,
languages: ['JavaScript', 'SQL', 'C#'], age: 32
},
{
id: 11,
years_of_experience: 3,
github_points: 232,
languages: ['Java', 'Ruby', 'JavaScript'],
age: 31
},
{
id: 11,
years_of_experience: 12,
github_points: 32,
languages: ['VB', 'Cobol', 'Fortran'],
age: 42
},
{
id: 13,
years_of_experience: 2,
github_points: 328,
languages: ['Python', 'Ruby', 'JavaScript'],
age: 25
},
{
id: 15,
years_of_experience: 1,
github_points: 400,
languages: ['JavaScript', 'Ruby'],
age: 16
},
]
我正在尝试使用参数id
并返回@candidates
中的哈希,其:id
的值与id
匹配。如果没有找到匹配项,则返回nil
。
我的方法如下:
def find(id)
for candidate in @candidates
if candidate[:id] == id
return candidate
else
return nil
end
end
end
find(15)
但是,它在数组中的第一项结束后立即返回nil
。它应继续到数组末尾并找到所有匹配项,如果找不到任何匹配项,则返回nil
,而不是第一个找不到匹配项的实例简单返回nil
。
感谢您的帮助。
答案 0 :(得分:5)
如果问题是您返回得太早,那么您可以简单地避免过早返回。这应该起作用:
def find(id)
for candidate in @candidates
if candidate[:id] == id
return candidate
end
end
nil
end
但是更好的方法是:
def find(id)
@candidates.find { |c| c[:id] == id }
end
答案 1 :(得分:1)
正如大卫·格雷森(David Grayson)指出的那样,直接的答案是你回来太早了。
一种可能更好的解决方案是基于id
作为密钥使用哈希的哈希而不是哈希的数组。这将比基于循环的查找有效得多,并且还将迫使您面对这样一个事实,即您的数据中有重复的id
。
@candidates = {
15 => {
years_of_experience: 4,
github_points: 293,
languages: ['C', 'Ruby', 'Python', 'Clojure'],
age: 26
},
7 => {
years_of_experience: 1,
github_points: 145,
languages: ['JavaScript', 'Ruby', 'Go', 'Erlang'],
age: 19
},
9 => {
years_of_experience: 6,
github_points: 435,
languages: ['JavaScript', 'SQL', 'C#'], age: 32
},
11 => {
id: 11,
years_of_experience: 3,
github_points: 232,
languages: ['Java', 'Ruby', 'JavaScript'],
age: 31
},
'11a' => { # note that you have two 11's!
years_of_experience: 12,
github_points: 32,
languages: ['VB', 'Cobol', 'Fortran'],
age: 42
},
13 => {
years_of_experience: 2,
github_points: 328,
languages: ['Python', 'Ruby', 'JavaScript'],
age: 25
},
'15a' => { # ditto for 15's
years_of_experience: 1,
github_points: 400,
languages: ['JavaScript', 'Ruby'],
age: 16
},
}
p @candidates[15] # => {:years_of_experience=>4, :github_points=>293, :languages=>["C", "Ruby", "Python", "Clojure"], :age=>26}
p @candidates[42] # => nil
请注意,您不需要find
方法,它只是普通的哈希访问。另外请注意,如果找不到匹配的nil
,则会返回id
。
答案 2 :(得分:0)
如果您正在运行许多这样的“查找一个”调用,则通过将列表转换为哈希值来索引列表会更好:
indexed_candidates = candidates.index_by { |obj| obj[:id] }
def find(id)
indexed_candidates[id]
end
这是O(1)来调用find
的时间,而O(N)每次都要遍历它。
但是,这取决于候选列表是静态的,如果您需要添加/删除,则需要重建或更新索引。
编辑
由于已指出index_by
不在ruby核心中(不过,您只需要require 'active_support/all
),如果您使用的是ruby 2.4或更高版本,则可以使用transform_values
:< / p>
indexed_candidates = candidates
.group_by { |obj| obj[:id] }
.transform_values(&:first)