解释一个ruby代码片段

时间:2010-01-03 07:34:32

标签: ruby

我正在尝试理解这段代码:

while row = input.gets
  row.strip!
  next if row.empty?

  valuesplit = row.split("---")
  a, b = valuesplit[1..2]
  unless a == b
    $hash1[a] ||= {} <--------------What is this line doing?  How is the whole loop
    $hash1[a][b] = true               being traversed?

    if $hash1[b] && $hash1[b][a] <-----Can you please describe this if() loop
      $hash2[a] ||= []
      $hash2[a] << b
      $hash2[b] ||= []
      $hash2[b] << a
    end
  end
end

注意:$ hash1 = {} $ hash2 = {}

谢谢!

更新

输入:

junkdata1 value1 value2
junkdata2 value3 value4
junkdata3 value5 value6

等等。

也更新了带注释的代码行。

3 个答案:

答案 0 :(得分:12)

# loops by reading in every line of the input
# (input can be a file or another I/O object)
# every line is stored successively in a variable
# called "row"
while row = input.gets

  # removes leading and trailing whitespace from
  # the string that is stored in the "row" variable
  row.strip! 

  # if the string is empty, continue to the next
  # line (go back to beginning of loop)
  next if row.empty? 

  # split the string into an array of substrings
  # based on the "---" delimiter
  valuesplit = row.split("---") 

  # assign the second substring in the valuesplit
  # array to a variable called a, and the third to
  # a variable called b
  a, b = valuesplit[1..2] 

  # if a and b are different
  unless a == b

    # initialize the hash1 dictionary's a entry
    # to an empty sub-dictionary if it is null
    $hash1[a] ||= {} 

    # in the hash1 dictionary, set a's entry
    # to a dictionary that has b as the entry
    # and true as the value
    $hash1[a][b] = true

    # if the value for the b entry in the hash1
    # dictionary is true (not false or null) AND the value for a's
    # entry of the dictionary found at the b
    # entry of the hash1 dictionary is true
    if $hash1[b] && $hash1[b][a] 

      # initialize the hash2 dictionary's a entry
      # to an empty arraylist if it null or false
      $hash2[a] ||= [] 

      # add b to this arraylist
      $hash2[a] << b

      # initialize the hash2 dictionary's b entry
      # to an empty arraylist if it null or false
      $hash2[b] ||= []

      # add a to this arraylist
      $hash2[b] << a 
    end # end of the if $hash1[b]... statement
  end # end of the unless a == b statement
end # end of the gets loop

答案 1 :(得分:5)

我仍然觉得这个问题有点模糊。您还应该注意我忽略了您的示例数据。给定您的示例数据,$ hash1和$ hash2的结果都是空哈希值。

关于你的第一个问题:

$hash1[a] ||= {}

以上是两件事的组合 首先是哈希的索引,我假设你很熟悉。 第二种是条件赋值。举个例子:

blah ||= 1

如上所述,只要blah为零,就将值1赋值给blah。如果blah不是nil则不执行赋值。

对于if语句,我们需要一些上下文:

if $hash1[b] && $hash1[b][a]  #if the pair exists reversed
  $hash2[a] ||= []            #initialize the array for the second
  $hash2[a] << b              #append the third to the second's array
  $hash2[b] ||= []            #likewise for the reverse
  $hash2[b] << a
end

如果我们假设$ hash1和$ hash2的初始值是{},并且如果我们假设输入是一系列---分隔值,那么给出以下数据集:

foo---b---c
foo---c---a
foo---a---b
foo---b---a
foo---a---d
foo---d---a

$ hash1的值为:

{"a"=>{"b"=>true, "d"=>true}, "b"=>{"a"=>true, "c"=>true}, "c"=>{"a"=>true}, "d"=>{"a"=>true}}

$ hash2将是:

{"a"=>["b", "d"], "b"=>["a"], "d"=>["a"]}

鉴于此,我可以做出有根据的猜测,即代码块正在生成关系字典。在上面,$ hash1列出给定值是否引用其他值。一种真理测试。如果您想知道A是否可以使用B,那么您可以使用:

$hash1['a']['b']

如果结果为真,那么答案是肯定的。

$ hash2是一种双向关系的字典。 如果您选中:

$hash2['a']

你会找到一个A引用的所有东西的数组,它也引用A。

干杯。

答案 2 :(得分:2)

 foo ||= bar

这是

的简写
 foo = foo || bar

就像它是Java中的简写一样。它基本上意味着“如果foo当前为零,则将foo设置为等于默认值bar,否则不要单独”(在ruby中为nil评估为false)