Ruby如何注入代码?

时间:2012-03-05 07:33:37

标签: ruby

我是Ruby的新手,我正在尝试编写一个方法,将一组单词分组为anagram组。这是代码:

def combine_anagrams(words)
  dict = words.inject(Hash.new(0)) do |list,ws|
    key = sort_word(ws)
    if !list.has_key?(key)
      list[key] = []
    end
    list[key].push(ws)
    list             #What is this
  end
  return dict.values
end   

我的问题是list的陈述是什么。如果我拿出它,列表就变成了数组而不是哈希。

4 个答案:

答案 0 :(得分:1)

每个方法/块/等。在Ruby中返回一些东西,除非有一个早期的return语句,无论方法/块/ etc中的最后一个语句是什么。是,是归还的。

在您的情况下,让list成为传递给inject的块中的最后一行,可确保块返回list。当你删除它时,会返回list[key].push(ws)的返回值,这显然不是你想要的。

请注意,此行为还会使return关键字成为最后一个将被执行的语句,否则是不必要的(这包括方法结束时的return)。虽然有些人更愿意明确表示他们打算退回某些东西,即使在不需要的时候也会使用它们。

在不相关的注释中:您的if !list.has_key?(key)可以重写unless list.has_key?(key)

答案 1 :(得分:1)

inject的工作原理如下:

final = enumerable.inject(initial_value) do |current_value, iteration|
  # calculations, etc. here
  value # next iteration, current_value will be whatever the block returns
end

因此,在您的情况下,initial_valueHash.new(0),或者为0的空哈希值作为不存在的密钥的默认值,而不是nil 。这将传递到inject中第一个元素的enumerable块。

在注入块内部,检查是否已将key作为哈希上的键存在。如果没有,则将其设置为空数组。在任何一种情况下,取当前迭代wordsws)并将其推送到数组上。

最后,该块返回当前版本的list;它将在下次循环处理来自current_value的元素时变为injectenumerable块的第一个参数)。

作为一个更简单的示例,请查看此示例:

numbers = [1, 2, 3, 4]
sum = inject(0) do |total, number| # first time, total will be 0
  total + number # set total next time to be whatever total is now plus the current number
end

答案 2 :(得分:0)

查看http://ruby-doc.org/core-1.9.3/Enumerable.html#method-i-inject

在inject方法中,如果你传入两个参数(在你的case列表和ws中),第一个 - list - 就是所谓的累加器值。每个迭代步骤中注入块返回的值被分配给列表变量。因此,使用您所评论为“#What is this”的唯一单词“list”的行用于将块中列表的值分配给“list”累加器变量。

答案 3 :(得分:0)

语句“list”是整个块的返回值。行:“list [key] = []”的返回值为“list”,因此它不需要另一行将if条件的返回值设置为'list',而是list [key]的返回值.push(ws)是列表[key]。我们希望最终得到列表的更新值,因此我们需要每次从块中返回该值,以便进一步处理更新列表的行为,而不是别的。

作为背景,每个ruby行也有一个返回值,所以如果它是一个块或函数的最后一行,它会自动成为整个块或函数的返回值。

要进一步理解这一点,请在irb中尝试这样的代码:

a = [1,2,3,4,5]
b = a.inject(0) {|sum, val| puts sum; puts val; sum + val}

内部块包括三个状态;最后一个语句将sum + val的值返回到块中,该值以sum的形式存储,以便在下一次迭代中使用。

另外,尝试这样的代码:

h = {:a => []}
b = h[:a].push 6

查看b评估的内容;在你的代码中,你需要'b'作为累积的哈希值,而不是存储在h [:a]

中的数组