How to split string into an array into two separate strings - ruby

I have the following Ruby on Rails params:
<ActionController::Parameters {"type"=>["abc, def"], "format"=>:json, "controller"=>"order", "action"=>"index"} permitted: false>
I want to check if there's a , in the string, then separate it into two strings like below and update type in params.
<ActionController::Parameters {"type"=>["abc", "def"], "format"=>:json, "controller"=>"order", "action"=>"index"} permitted: false>
I tried to do like below:
params[:type][0].split(",") #=> ["abc", " def"]
but I am not sure why there's a space before the second string.
How can I achieve that?

Because there's a whitespace in your string, that's why the result of using split will also include it in the splitted element for the array.
You could remove first the whitespaces and then use split. Or add ', ' as the split value in order it takes the comma and the space after it. Or depending on the result you're trying to get, to map the resulting elements in the array and remove the whitespaces there, like:
string = 'abc, def'
p string.split ',' # ["abc", " def"]
p string.split ', ' # ["abc", "def"]
p string.delete(' ').split ',' # ["abc", "def"]
p string.split(',').map &:strip # ["abc", "def"]

Related

Ruby: how to dasherize un String without using ActiveSupport

As the title says, I'd like to dasherize a String by chunks of 3 characters, e.g.:
str = '123456789'
str.dasherize => # '123-456-789'
It should be done outside Rails ActiveSupport or any other gems.
You could do:
'123456789'.scan(/.{1,3}/).join('-')
#=> "123-456-789"
'1234567890'.scan(/.{1,3}/).join('-')
#=> "123-456-789-0"
'12345678901'.scan(/.{1,3}/).join('-')
#=> "123-456-789-01"
This is splitting the string into an Array of 1-3 character chunks, then re-joining them with a hyphen.
You didn't specify how such a method should behave if the string's length is not a multiple of 3, but you could tweak the above approach to get some other result if desired.
One liner:
"123456789".chars.each_slice(3).map(&:join).join('-')
Explanation:
"123456789"
.chars # returns an Enumerator that yields each character
.each_slice(3) # groups the previous iterator into chunks of 3: ['1', '2', '3']
.map(&:join) # join the sub groups into strings: "123", "456"
.join("-") # finally, join the resulting groups with dashes.
Without regular expressions, with step
string = '123456789'
(string.size - 3).step(1, -3) do |i|
string.insert(i, '-')
end
puts string

Matching groups of words

I would like a regexp that match all groups of words (single words and sub-sentences) in a sentence separated by white space.
Example :
"foo bar bar2".scan(regexp)
I want a regexp that will returns :
['foo', 'bar', 'bar2', 'foo bar', 'bar bar2', 'foo bar bar2']
So far, I tried :
"foo bar bar2".scan(/\S*[\S]/) (ie regexp=/\S*/)
which returns ['foo', 'bar', 'bar2']
"foo bar bar2".scan(/\S* [\S]+/) (ie regexp=/\S* [\S]+/)
which returns ["foo bar", " bar2"]
words = "foo bar bar2".scan(/\S+/)
result = 1.upto(words.length).map do |n|
words.each_cons(n).to_a
end.flatten(1)
#⇒ [["foo"], ["bar"], ["bar2"],
# ["foo", "bar"], ["bar", "bar2"],
# ["foo", "bar", "bar2"]]
result.map { |e| e.join(' ') }
#⇒ ["foo", "bar", "bar2", "foo bar", "bar bar2", "foo bar bar2"]
Here we used Enumerable#each_cons to get to the result.
Mudasobwa did a nice variation of this answer check here.
I've used combine , builtin method for arrays. The procedure is almost the same:
string = "foo bar bar2"
groups = string.split
objects = []
for i in 1..groups.size
groups = string.split.combination(i).to_a
objects << groups
end
results = objects.flatten(1).map { |e| e.join('-') }
puts results
Anyway , you can't do it with one regex.(suppose you have 50 words and need to find all the combinations; regex can't do it). You will need to iterate with the objects like Mudasobwa showed.
I would start doing this: the regex, if you want to use one, can be /([^\s]\w+)/m ; for example.
This regex will match words. And by words I mean groups of characters surrounded by white-spaces.
With this you can scan your text or split your string. You can do it many ways and in the end you will have an array with the words you wanna combine.
string = "foo bar bar2"
Then you split it, creating an array and applying to it the combination method.
groups = string.split
=> ["foo", "bar", "bar2"]
combination method takes a number as argument, and that number will be the 'size' of the combination. combination(2) combines the elements in groups of two. 1 - groups of 1 .. 0 groups of zero! (this is why we start combinations with 1).
You need to loop and cover all possible group sizes, saving the results
in a results array. :
objects = []
use the number of elements as parameter to the loop
for i in 1..groups.size
groups = string.split.combination(i).to_a
objects << groups
end
Now you just have to finish with a loop to flatten the arrays that are inside arrays and to take out the comas and double quotes
results = objects.flatten(1).map { |e| e.join('-') }
Thats it! You can run the code above (example with more words)here https://repl.it/JLK9/1
Ps: both question and the mentioned answer are lacking a combination (foo-bar2)

ruby regexp to find a word that does not contain digits

I want my regular expression to return an enumerator that would return blocks with words that are not digits, what is the best way I could get that?
I have tried following:
regexp= /(?=\w+)(?=^(?:(?!\d+).)*$)/
"this is a number 1234".split(regexp) # ["this is a number 1234"]
where I expected (?=\w+) should ensure if that is word or not and I expected (?=^(?:(?!\d+).)*$) to ensure it does not contain any digits.
I expected an output:
["this", "is", "a", "number"]
scan is easier than split for this:
regexp = /\b[[:alpha:]]+\b/
p "this is a number 1234".scan(regexp)
# => ["this", "is", "a", "number"]
Try Following.
p "this is a number 1234".scan(/\D+/).first.split(' ')

How could I split string and keep the whitespaces, as well?

I did the following in Python:
s = 'This is a text'
re.split('(\W)', s)
# => ['This', ' ', 'is', ' ', 'a', 'text']
It worked just great. How do I do the same split in Ruby?
I've tried this, but it eats up my whitespace.:
s = "This is a text"
s.split(/[\W]/)
# => ["This", "is", "a", "text"]
From the String#split documentation:
If pattern contains groups, the respective matches will be returned in
the array as well.
This works in Ruby the same as in Python, square brackets are for specify character classes, not match groups:
"foo bar baz".split(/(\W)/)
# => ["foo", " ", "bar", " ", "baz"]
toro2k's answer is most straightforward. Alternatively,
string.scan(/\w+|\W+/)

Break up variable into array in Ruby

I'd like to take a variable that I have, and turn it into an array separated by the character of my choosing. In the example below, that separator is %
dump = "1%2%3%apple%car%yellow"
into
Array= [1,2,3,apple,car,yellow]
Use String#split:
"1%2%3%apple%car%yellow".split('%')
# => ["1", "2", "3", "apple", "car", "yellow"]
(Note that every element of the returned array is a string, even the ones containing digits.)
From the docs:
split (pattern=$;, [limit]) → anArray
Divides
str into substrings based on a delimiter, returning an array of these
substrings.
You can pass a string like above ('%'), or a regular expression.

Resources