
Ops Scripting w. Ruby: Frequency 2
Tracking Frequency in Ruby: Part II
Updated: 2020–05–24
This is continuation of series on building Ruby frequency hash to solve common problems in operations scripting. Previously, I described the problem as well as gave a sample data file.
Now, we’ll start to discuss solutions and discussions about Ruby language features.
The Solutions
These solutions we’ll use a conditional while
loop in conjunction with the gets
method. The gets
will return false once it gets an EOL (end-of-line) marker, otherwise, it returns true.
Solution 1: Conditionally Initialize new Hash Value
We open the file and iterate line by line in this example:
We only care about the shell in each line, so we can do a few operations to extract the line. First, chomp off the newline, then split the line into a list, where we slice off the 7th item (indexed by 6):
line = line.chomp # strip newline
line_items = line.split(/:/) # split up line by ':' divider
shell = line_items[6] # slice off 7th item
This can all be done in a single line.
shell = (line.chomp.split(/:/))[6]
Now that we extracted the shell, we need to check if we actually got a shell.
if shell != nil
# do stuff with that shell, using shell string as a key
end
Each item in the counts
hash will have a key that represents the shell, and a value that represents frequency of shell used in our data file passwd
.
We simply need to increment the value. As Ruby does not initialize values to a default value when first used, we have to do this process manually.
# initialize new key if key doesn't exist in hash
if ! counts.has_key? shell
counts[shell] = 0
end
# increment the count
counts[shell] += 1
Alternatively, we could write the same branch logic using ternary operator ?:
:
counts[shell] = counts.has_key?(shell) ? counts[shell] += 1 : 1
Solution 2: Auto Assign a Default Value
Instead of conditionally setting the frequency count with branch logic, we can use ruby’s ||=
operator, which sets a default value for a key that does not yet exist..
In our solution, we set the default of a key that does not yet exist to 0
, and then increment that value by one.
counts[shell] = (counts[shell] ||= 0) + 1
We also only do this whole operation if we have a valid shell.
counts[shell] = (counts[shell] ||= 0) + 1 if shell != nil
Solution 3: Hash with Default Value
Another method is to just to set all keys that do not yet exist to have a default. We can do this with the Hash.new()
method instead of {}
to create an empty hash.
After this, we no longer need logic to handle conditionally initializing a new hash item.
This allows ruby to behave like other languages that have defaults, but gives us greater control to set the default to one of our choosing.
Conclusion
From these solutions, the you should have picked up the following takeaways for Ruby:
- Iterating through a file with
while
andgets
- Splitting a String
- List Slicing (or indexing in this case)
- Testing variable is initialized
- 3 ways to initialize default value in hash class
In the next article, I will show how to use functional programming style to this problem with map()
and select()
.