Ruby Array changing substring - ruby

I would like to display the following:
anu1 cau1 doh1 bef1
To do that I need to complete the following Ruby code by adding only ONE statement.
a = ["ant", "cat", "dog", "bee"]

It sounds like you need to perform a succ function each of the words, which will give you the next value for each of them, then you would just need to append "1" to each.
Example: -Forgive my syntax, Haven't used Ruby in a while-
a.map {|word| word.succ << "1"}
should output:
["anu1", "cau1", "doh1", "bef1"]

a = ["ant", "cat", "dog", "bee"]
# => ["ant", "cat", "dog", "bee"]
a.map {|str| str.succ << "1" }
# => ["anu1", "cau1", "doh1", "bef1"]

Related

Find out if a specified number of array elements match

What's a simple way to write a method for checking if a certain number of array elements match. For example
["dog", "cat", "dog", "dog"].has_matching(3)
# true
and
["dog", "cat", "dog", "cat"].has_matching(3)
# false
Ideally the class of the objects being compared would not matter.
You could add a method to Array:
class Array
def check_if_minimum_duplicates(min_dup)
group_by{|el| el }.any?{|k, v| v.count >= min_dup }
end
end
and use it like this:
irb(main):006:0> puts ["dog", "cat", "dog", "dog"].check_if_minimum_duplicates(3)
true
=> nil
irb(main):007:0> puts ["dog", "cat", "dog", "cat"].check_if_minimum_duplicates(4)
false
=> nil

Split a string in Ruby

I have a hash returned to me in ruby
test_string = "{cat=6,bear=2,mouse=1,tiger=4}"
I need to get a list of these items in this form ordered by the number.
animals = [cat, tiger, bear, mouse]
My thoughts were to_s this in ruby and split on the '=' character. Then try to order them and put in a new list. Is there an easy way to do this in ruby? Sample code would be greatly appreciated.
s = "{cat=6,bear=2,mouse=1,tiger=4}"
a = s.scan(/(\w+)=(\d+)/)
p a.sort_by { |x| x[1].to_i }.reverse.map(&:first)
a = test_string.split('{')[1].split('}').first.split(',')
# => ["cat=6", "bear=2", "mouse=1", "tiger=4"]
a.map{|s| s.split('=')}.sort_by{|p| p[1].to_i}.reverse.map(&:first)
# => ["cat", "tiger", "bear", "mouse"]
Not the most elegant way to do it, but it works:
test_string.gsub(/[{}]/, "").split(",").map {|x| x.split("=")}.sort_by {|x| x[1].to_i}.reverse.map {|x| x[0].strip}
The below code should do it.
Explained the steps inline
test_string.gsub!(/{|}/, "") # Remove the curly braces
array = test_string.split(",") # Split on comma
array1= []
array.each {|word|
array1<<word.split("=") # Create an array of arrays
}
h1 = Hash[*array1.flatten] # Convert Array into Hash
puts h1.keys.sort {|a, b| h1[b] <=> h1[a]} # Print keys of the hash based on sorted values
test_string = "{cat=6,bear=2,mouse=1,tiger=4}"
Hash[*test_string.scan(/\w+/)].sort_by{|k,v| v.to_i }.map(&:first).reverse
#=> ["cat", "tiger", "bear", "mouse"]

Strip in collect on splitted array in Ruby

The following code:
str = "1, hello,2"
puts str
arr = str.split(",")
puts arr.inspect
arr.collect { |x| x.strip! }
puts arr.inspect
produces the following result:
1, hello,2
["1", " hello", "2"]
["1", "hello", "2"]
This is as expected. The following code:
str = "1, hello,2"
puts str
arr = (str.split(",")).collect { |x| x.strip! }
puts arr.inspect
Does however produce the following output:
1, hello,2
[nil, "hello", nil]
Why do I get these "nil"? Why can't I do the .collect immediately on the splitted-array?
Thanks for the help!
The #collect method will return an array of the values returned by each block's call. In your first example, you're modifying the actual array contents with #strip! and use those, while you neglect the return value of #collect.
In the second case, you use the #collect result. Your problem is that #strip! will either return a string or nil, depending on its result – especially, it'll return nil if the string wasn't modified.
Therefore, use #strip (without the exclamation mark):
1.9.3-p194 :005 > (str.split(",")).collect { |x| x.strip }
=> ["1", "hello", "2"]
Because #strip! returns nil if the string was not altered.
In your early examples you were not using the result of #collect, just modifying the strings with #strip!. Using #each in that case would have made the non-functional imperative loop a bit more clear. One normally uses #map / #collect only when using the resulting new array.
You last approach looks good, you wrote a functional map but you left the #strip! in ... just take out the !.

Ruby: How do I make a loop that prints an array index position's contents UNLESS it's the same as the last position's?

Here's my array:
num_arr = ["cat","dog","penguin","penguin"]
I want to print each index position's contents unless those contents are the same as the contents of the last index position. In this case, that would be a loop that prints...
["cat","dog","penguin"]
EDIT: I mean I'd like to print everything up to the last element UNLESS the last element is identical to the second-to-last element. Sorry for the confusion.
What about this?
num_arr[0...-1] + (num_arr[-2] == num_arr[-1] ? [] : [num_arr[-1]])
Less verbose, but somewhat more difficult to undestand:
num_arr[0...-2] + num_arr[-2..-1].uniq
#=> ["cat", "dog", "penguin"]
foo = ["cat","dog","penguin","penguin"]
=> ["cat", "dog", "penguin", "penguin"]
answer = foo.reject { |ele| ele == foo.last }
=> ["cat", "dog"]
I believe this is what you're asking for.
new_array = array.each_with_object([]) { |element, result| result << element unless result.last == element }
new_array.each { |element| puts element }
If you just want to print all unique entries use the uniq method of Array in this case.
["cat","dog","penguin","penguin"].uniq.map{|a| p a}
console
ruby-1.9.2-p290 :004 > ["cat","dog","penguin","penguin"].uniq.map{|a| p a}
"cat"
"dog"
"penguin"
=> ["cat", "dog", "penguin"]
Update:
If you want to only do a comparison for the last entry, you could do that by storing the last entry in #prev and assigning it after the comparison to the current entry.
["cat", "dog", "penguin", "penguin"].map{|a| p a if #prev!=a;#prev=a }
console
ruby-1.9.2-p290 :009 > ["cat", "dog", "penguin", "dog", "penguin"].map{|a| p a if #prev!=a;#prev=a }
"cat"
"dog"
"penguin"
"dog"
"penguin"
ruby-1.9.2-p290 :010 > ["cat", "dog", "penguin", "penguin"].map{|a| p a if #prev!=a;#prev=a }
"cat"
"dog"
"penguin"

How do you replace a string with a hash collection value in Ruby?

I have a hash collection:
my_hash = {"1" => "apple", "2" => "bee", "3" => "cat"}
What syntax would I use to replace the first occurrence of the key with hash collection value in a string?
eg my input string:
str = I want a 3
The resulting string would be:
str = I want a cat
My one liner:
hash.each { |k, v| str[k] &&= v }
or using String#sub! method:
hash.each { |k, v| str.sub!(k, v) }
"I want a %{b}" % {c: "apple", b: "bee", a: "cat"}
=> "I want a bee"
Assuming Ruby 1.9 or later:
str.gsub /\d/, my_hash
I didn't understand your problem, but you can try this:
my_hash = {"1" => "apple", "2" => "bee", "3" => "cat"}
str = "I want a 3"
str.gsub(/[[:word:]]+/).each do |word|
my_hash[word] || word
end
#=> "I want a cat"
:D
Just to add point free style abuse to fl00r's answer:
my_hash = {"1" => "apple", "2" => "bee", "3" => "cat"}
my_hash.default_proc = Proc.new {|hash, key| key}
str = "I want a 3"
str.gsub(/[[:word:]]+/).each(&my_hash.method(:[]))
my_hash = {"1" => "apple", "2" => "bee", "3" => "cat"}
str = "I want a 3"
If there isn't any general pattern for the strings you want to substitute, you can use:
str.sub /#{my_hash.keys.map { |s| Regexp.escape s }.join '|'}/, my_hash
But if there is one, the code becomes much simpler, e.g.:
str.sub /[0-9]+/, my_hash
If you want to substitute all the occurrences, not only the first one, use gsub.
You can use String.sub in ruby 1.9:
string.sub(key, hash[key])
The following code replace the first occurrence of the key with hash collection value in the given string str
str.gsub(/\w+/) { |m| my_hash.fetch(m,m)}
=> "I want a cat"

Resources