Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 8 years ago.
Improve this question
I have str = "1, 2, a, 3, 4, z"
I want to use Regex to find and add .3 to the end of all the digits and a colon : to the beginning of all the characters. So the desired output would be:
"1.3, 2.3, :a, 3.3, 4.3, :z"
Can I do that with gsub in Ruby? Is that the most efficient way?
String#gsub accepts optional block. The return value of the block is used as substitution string.
str = "1, 2, a, 3, 4, z"
str.gsub(/\d+|[a-z]+/i) { |x| x =~ /\d/ ? x + '.3' : ':' + x }
# => "1.3, 2.3, :a, 3.3, 4.3, :z"
using capturing group:
str.gsub(/(\d+)|([a-z]+)/i) { $1 ? $1 + '.3' : ':' + $2 }
# => "1.3, 2.3, :a, 3.3, 4.3, :z"
From String#gsub documentation:
If replacement is a String it will be substituted for the matched
text. It may contain back-references to the pattern’s capture groups
of the form \d, where d is a group number, or \k, where n is a
group name. If it is a double-quoted string, both back-references must
be preceded by an additional backslash. However, within replacement
the special match variables, such as $&, will not refer to the current
match.
The solution:
str = "1, 2, a, 3, 4, z"
str.gsub(/(\d)+/, '\1.3').gsub(/([a-z])+/i, ':\1')
# => "1.3, 2.3, :a, 3.3, 4.3, :z"
Non-regexp and gsub version:
str = "1, 2, a, 3, 4, z"
result = str.split(', ').map do |chr|
case chr.downcase
when 'a'..'z' then ":#{chr}"
when '1'..'9' then "#{chr}.3"
end
end.join(', ')
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I would like to ask you for help. I have keywords in this form "AB10" and I need to split i to "AB" and "10". What is the best way?
Thank you for your help!
One could use String#scan:
def divide_str(s)
s.scan(/\d+|\D+/)
end
divide_str 'AB10' #=> ["AB", "10"]
divide_str 'AB10CD20' #=> ["AB", "10", "CD", "20"]
divide_str '10AB20CD' #=> ["10", "AB", "20", "CD"]
The regular expression /\d+|\D+/ reads, "match one or more (+) digits (\d) or one or more non-digits (\D).
Here is another way, one that does not employ a regular expression.
def divide_str(s)
digits = '0'..'9'
s.each_char.slice_when do |x,y|
digits.cover?(x) ^ digits.cover?(y)
end.map(&:join)
end
divide_str 'AB10' #=> ["AB", "10"]
divide_str 'AB10CD20' #=> ["AB", "10", "CD", "20"]
divide_str '10AB20CD' #=> ["10", "AB", "20", "CD"]
See Enumerable#slice_when, Range#cover?, TrueClass#^ and FalseClass#^.
Use split like so:
my_str.split(/(\d+)/)
To split any string on the boundary between digits and letters, use either of these 2 methods:
Use split with regex in capturing parentheses to include the delimiter, here a stretch of digits, into the resulting array. Remove empty strings (if any) using a combination of reject and empty?:
strings = ['AB10', 'AB10CD20', '10AB20CD']
strings.each do |str|
arr = str.split(/(\d+)/).reject(&:empty?)
puts "'#{str}' => #{arr}"
end
Output:
'AB10' => ["AB", "10"]
'AB10CD20' => ["AB", "10", "CD", "20"]
'10AB20CD' => ["10", "AB", "20", "CD"]
Use split with non-capturing parentheses: (?:PATTERN), positive lookahead (?=PATTERN) and positive lookbehind (?<=PATTERN) regexes to match the letter-digit and digit-letter boundaries:
strings.each do |str|
arr = str.split(/ (?: (?<=[A-Za-z]) (?=\d) ) | (?: (?<=\d) (?=[A-Za-z]) ) /x)
puts "'#{str}' => #{arr}"
end
The two methods give the same output for the cases shown.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
I have an array, and I need to print it out all on one line:
numbers = Array[[2, 4, 4, 5, 5, 7, 9]
Instead of separate lines how can I code this? I heard Array.join('') but I tried this code and it wouldn't run.
Always remember that the Ruby manual is your friend. If you read the manual for Array#join you will find some good candidates:
join(p1 = v1) public
Returns a string created by converting each element of the array to a string, separated by the given separator. If the separator is nil, it uses current $,. If both the separator and $, are nil, it uses an empty string.
[ "a", "b", "c" ].join #=> "abc"
[ "a", "b", "c" ].join("-") #=> "a-b-c"
So, now we can try:
numbers = [1, 2, 3, 4, 5]
puts numbers.join(" ")
Outputs:
1 2 3 4 5
Try
p numbers
This will print your array on a single line (which will obviously overflow depending on your window width).
You can use either method
puts numbers.join(', ');
or
puts numbers.inspect
Here is the code
string = "Looking for the ^[cows]"
footnote = string[/\^\[(.*?)\]/]
I was hoping that footnote would equal cows
What I get is footnote equals ^[cows]
Any help?
Thanks!
You can specify which capture group you want with a second argument to []:
string = "Looking for the ^[cows]"
footnote = string[/\^\[(.*?)\]/, 1]
# footnote == "cows"
According to the String documentation, the #[] method takes a second parameter, an integer, which determines the matching group returned:
a = "hello there"
a[/[aeiou](.)\1/] #=> "ell"
a[/[aeiou](.)\1/, 0] #=> "ell"
a[/[aeiou](.)\1/, 1] #=> "l"
a[/[aeiou](.)\1/, 2] #=> nil
You should use footnote = string[/\^\[(.*?)\]/, 1]
If you want to capture subgroups, you can use Regexp#match:
r = /\^\[(.*?)\]/
r.match(string) # => #<MatchData "^[cows]" 1:"cows">
r.match(string)[0] # => "^[cows]"
r.match(string)[1] # => "cows"
An alternative to using a capture group, and then retrieving it's contents, is to match only what you want. Here are three ways of doing that.
#1 Use a positive lookbehind and a positive lookahead
string[/(?<=\[).*?(?=\])/]
#=> "cows"
#2 Use match but forget (\K) and a positive lookahead
string[/\[\K.*?(?=\])/]
#=> "cows"
#3 Use String#gsub
string.gsub(/.*?\[|\].*/,'')
#=> "cows"
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 8 years ago.
Improve this question
Could someone please explain lines 5 and 6? On line 5, is |word| a parameter? Why is it needed there? Also, on line 6, are {|a, b| b} also parameters. How should one read line 6? What is it doing?
puts "Input something: " # 1
text = gets.chomp # 2
words = text.split # 3
frequencies = Hash.new(0) # 4
words.each { |word| frequencies[word] += 1 } # 5
frequencies = frequencies.sort_by {|a, b| b} # 6
frequencies.reverse! # 7
On line 5, is |word| a parameter?
Yes, it's a block argument.
Why is it needed there?
From Array#each's documentation: "Calls the given block once for each element in self, passing that element as a parameter."
Example:
words = ["foo", "bar", "baz"]
words.each { |word| puts word }
The block is called three times. On the first pass, its block argument word is set to "foo", on the second pass it's set to "bar" and on the third pass it's set to "baz". Each time word is printed using puts.
Output:
foo
bar
baz
In your example, a hash is used to store the word frequencies. Within the each loop, the word's count is incremented.
How should one read line 6? What is it doing?
Enumerable#sort_by sorts a collection by the block's result. For example, to sort an array of strings by the string's length you would use:
["xxx", "xx", "x"].sort_by { |str| str.length }
#=> ["x", "xx", "xxx"]
Since frequencies is a hash, the block is called for each pair. Therefore, two arguments are set - a is the pair's key and b is the pair's value:
frequencies = { "foo" => 3, "bar" => 2, "baz" => 1}
frequencies = frequencies.sort_by { |a, b| b }
#=> [["baz", 1], ["bar", 2], ["foo", 3]]
It sorts the hash by its values. Note that sort_by returns an array. The array is assigned to the frequencies variable.
Instead of a and b you could use more descriptive argument names:
frequencies.sort_by { |word, count| count }
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What is the * operator doing to this string in Ruby
I ran across the following code when looking for an easy way to convert an array to a hash (similar to .Net's ToDictionary method on IEnumerable... I wanted to be able to arbitrarily set the key and the value).
a = [ 1, 2, 3, 4, 5, 6 ]
h = Hash[ *a.collect { |v| [ v, v ] }.flatten ]
My question is, what does the asterisk before a.collect do?
By the way, the code comes from http://justatheory.com/computers/programming/ruby/array_to_hash_one_liner.html
It's the splat-operator if you want to google it. It does transform an array into a list (so you can use an array as arguments to a method). It also does the opposite: it can 'slurp' a list into an array.
require 'date'
*date_stuff = 2012,2,29 # slurp
p date_stuff #=> [2012, 2, 29]
Date.new(*date_stuff) # regurgitate