Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I have a String like this in Ruby: "33255563"
Is it possible to create an Array like this: ["33", "2", "555", "6", "3"] ?
Try this
s.each_char.chunk_while(&:==).map(&:join)
=> ["33", "2", "555", "6", "3"]
Input
a="33255563"
Program
p a.chars.slice_when{|a,b|a!=b}.map(&:join)
Output
["33", "2", "555", "6", "3"]
str = "33255563"
str.gsub(/(.)\1*/).to_a
#=> ["33", "2", "555", "6", "3"]
This uses String#gsub with one argument and no block, which returns an enumerator. This form of gsub performs no substitutions; it merely generates matches of the given pattern, which here is a regular expression.
We can write the regular expression in free-spacing mode to make it self-documenting.
/
(.) # match any character and save to capture group 1
\1* # match the content of capture group 1 zero or more times,
# as many as possible
/x # invoke free-spacing regex definition mode
Note that String#scan cannot be used because the regular expression contains a capture group.
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 5 years ago.
Improve this question
x = ["1", "2", "3", "4"]
#=> ["1", "2", "3", "4"]
x.split(", ")
#=> NoMethodError: undefined method `split' for ["1", "2", "3", "4"]:Array
The String#split method in ruby is used to divide a string into substrings
'a,b,c,d'.split(',') # => ["a", "b", "c", "d"]
You are trying to invoke Array#split (aka on an array object). As such array method doesn't exists, you get:
error undefined method split for ["1", "2", "3", "4"]:Array`
Arrays can't be split. You are probably thinking of splitting a string?
You will reach the desired value by simply x[0] for the 0 index, first object in the array.
This to any help?
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 8 years ago.
Improve this question
I'm trying to use a Regular Expression to find all sub strings in word. It is finding some but not all. On such example is 'an' in the word 'banana'.
def substrings str
pattern = '.'
subs = []
while pattern.length < str.length do
subs << str.scan(/#{pattern}/)
pattern << '.'
end
subs.flatten
end
puts substrings("banana").sort_by{ |s| "banana".index(/#{s}/)}
Regular expression matches will never overlap. If you ask for /../, you will get ["ba", "na", "na"]. You will not get ["ba", "an" ...] because "an" overlaps "ba". The next match search will start from the last match's end, always.
If you want to find overlapping sequences, you need to use lookahead/lookbehind to shorten your match size so the matches themselves don't overlap: /(?=(..))/. Note that you have to introduce a capture group, since the match itself is an empty string in this case.
def substrings str
(0...str.length).flat_map{|i| (i...str.length).map{|j| str[i..j]}}.uniq
end
substrings("banana")
Result
[
"b",
"ba",
"ban",
"bana",
"banan",
"banana",
"a",
"an",
"ana",
"anan",
"anana",
"n",
"na",
"nan",
"nana"
]
or
def substrings str
(0...str.length).to_a.combination(2).map{|r| str[*r]}.uniq
end
Result
[
"b",
"ba",
"ban",
"bana",
"banan",
"banana",
"an",
"ana",
"anan",
"anana",
"nan",
"nana",
"na",
"a"
]
Here's another way that does not use a regex. I see now how it can be done with a regex, but I don't know why you'd want to, unless it's just an exercise.
def substrings(str)
arr = str.chars
(1..str.size).each_with_object([]) { |i,a|
a << arr.each_cons(i).to_a.map(&:join) }.flatten
end
substrings("banana")
#=> ["b", "a", "n", "a", "n", "a", "ba", "an", "na", "an", "na", "ban",
# "ana", "nan", "ana", "bana", "anan", "nana", "banan", "anana"]
If you want to include the word "banana", change str.size to str.size+1.
This question already has answers here:
How do I avoid trailing empty items being removed when splitting strings?
(1 answer)
Empty strings at the beginning and end of split [duplicate]
(2 answers)
Closed 9 years ago.
I observed a strange behavior of the split method on a String.
"1..2".split('..') # => ['1', '2']
"1..2".split('..', 2) # => ['1', '2']
"..2".split('..') # => ['', '2']
"..2".split('..', 2) # => ['', '2']
Everything like expected, but now:
"1..".split('..') # => ['1']
"1..".split('..', 2) # => ['1', '']
I would expect the first to return the same that the second.
Does anyone have a good explanation, why "1..".split('..') returns an array with just one element? Or is it an inconsistency in Ruby? What do you think about that?
According to the Ruby String documentation for split:
If the limit parameter is omitted, trailing null fields are suppressed.
Regarding the limit parameter, the Ruby documentation isn't totally complete. Here is a little more detail:
If limit is positive, split returns at most that number of fields. The last element of the returned array is the "rest of the string", or a single null string ("") if there are fewer fields than limit and there's a trailing delimiter in the original string.
Examples:
"2_3_4_".split('_',3)
=> ["2", "3", "4_"]
"2_3_4_".split('_',4)
=> ["2", "3", "4", ""]
If limit is zero [not mentioned in the documentation], split appears to return all of the parsed fields, and no trailing null string ("") element if there is a trailing delimiter in the original string. I.e., it behaves as if limit were not present. (It may be implemented as a default value.)
Example:
"2_3_4_".split('_',0)
=> ["2", "3", "4"]
If limit is negative, split returns all of the parsed fields and a trailing null string element if there is a trailing delimiter in the original string.
Example:
"2_3_4".split('_',-2)
=> ["2", "3", "4"]
"2_3_4".split('_',-5)
=> ["2", "3", "4"]
"2_3_4_".split('_',-2)
=> ["2", "3", "4", ""]
"2_3_4_".split('_',-5)
=> ["2", "3", "4", ""]
It would seem that something a little more useful or interesting could have been done with the negative limit.
Is it possible to catch all grous of same digits in string with regex on Ruby? I'm not familiar with regex.
I mean: regex on "1112234444" will produce ["111", "22", "3", "4444"]
I know, I can use (\d)(\1*), but it only gives me 2 groups in each match. ["1", "11"], ["2", "2"], ["3", -], ["4", "444"]
How can I get 1 group in each match? Thanks.
Here, give this a shot:
((\d)\2*)
You can use this regex
((\d)\2*)
group 1 catches your required value
My first quick answer was rightfully criticized for having no explanation for the code. So here's another one, better in all respects ;-)
We exploit the fact that the elements whose runs we want are digits and they are easy to enumerate by hand. So we construct a readable regex which means "a run of zeros, or a run of ones, ... or a run of nines". And we use the right method for the job, String#scan:
irb> "1112234444".scan(/0+|1+|2+|3+|4+|5+|6+|7+|8+|9+/)
=> ["111", "22", "3", "4444"]
For the record, here's my original answer:
irb> s = "1112234444"
=> "1112234444"
irb> rx = /(0+|1+|2+|3+|4+|5+|6+|7+|8+|9+)/
=> /(0+|1+|2+|3+|4+|5+|6+|7+|8+|9+)/
irb> s.split(rx).reject(&:empty?)
=> ["111", "22", "3", "4444"]