开发者

Explain a ruby code snippet

I am trying to understand this code snippet:

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

NOTE: $hash1 = {} $hash2 = {}

Thanks!

UPDATE

Input:

junkdata1 value1 value2
junkdata2 va开发者_C百科lue3 value4
junkdata3 value5 value6

and so on.

Updated the code lines with comments too.


# 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


I still feel the question is a little vague. You should also note that I have ignored your example data. Given your example data, the results of both $hash1 and $hash2 are empty hashes.

For your first question:

$hash1[a] ||= {}

The above is a combination of two things First is an index into a hash which I'll assume you're familiar with. The second is sort of a conditional assignment. As an example:

blah ||= 1

The above says, assign the value 1 to blah as long as blah is nil. If blah is not nil then the assignment is not performed.

For the if statement we'll need some context:

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

If we assume that the initial values of $hash1 and $hash2 are {} as you note, and if we assume the input are a series of --- delimted values, then given the following data set:

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

The value of $hash1 would be:

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

Where $hash2 would be:

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

Given this, I can make an educated guess that the block of code is generating a dictionary of relationships. In the above, $hash1 lists whether a given value refers to other values. A sort of a truth test. If you wanted to know if A referred to B you could just use:

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

If the result is true then the answer is yes.

$hash2 is a sort of dictionary of two way relationships. If you checked:

$hash2['a']

You would find an array of all the things to which A refers which also refer to A.

Cheers.


 foo ||= bar

This is shorthand for

 foo = foo || bar

Just like it is shorthand in Java. It basically means "set foo equal to the default of bar if foo is currently nil, otherwise leave it alone" (nil evaluates to false in ruby)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜