gsub returns the string, or nil. Is there a way to have it return the number of replacements it has made?
I can think of using gsub block like this:
count = 0
str.gsub(/pat/) { |a| count+=1; "replacement" }
Example:
str = "lets replace all s with S"
count = 0
str.gsub("s") { |a| count+=1; "S" }
count
#=> 2
In Ruby gsub without second argument returns an Enumerator and you can use it:
str = 'your string'
new_str = str.gsub(/your/, 'my')
count = str.gsub(/your/).count
Related
I am trying to remove punctuation from an array of words without using regular expression. In below eg,
str = ["He,llo!"]
I want:
result # => ["Hello"]
I tried:
alpha_num="abcdefghijklmnopqrstuvwxyz0123456789"
result= str.map do |punc|
punc.chars {|ch|alpha_num.include?(ch)}
end
p result
But it returns ["He,llo!"] without any change. Can't figure out where the problem is.
include? block returns true/false, try use select function to filter illegal characters.
result = str.map {|txt| txt.chars.select {|c| alpha_num.include?(c.downcase)}}
.map {|chars| chars.join('')}
p result
str=["He,llo!"]
alpha_num="abcdefghijklmnopqrstuvwxyz0123456789"
Program
v=[]<<str.map do |x|
x.chars.map do |c|
alpha_num.chars.map.include?(c.downcase) ? c : nil
end
end.flatten.compact.join
p v
Output
["Hello"]
exclusions = ((32..126).map(&:chr) - [*'a'..'z', *'A'..'Z', *'0'..'9']).join
#=> " !\"\#$%&'()*+,-./:;<=>?#[\\]^_`{|}~"
arr = ['He,llo!', 'What Ho!']
arr.map { |word| word.delete(exclusions) }
#=> ["Hello", "WhatHo"]
If you could use a regular expression and truly only wanted to remove punctuation, you could write the following.
arr.map { |word| word.gsub(/[[:punct:]]/, '') }
#=> ["Hello", "WhatHo"]
See String#delete. Note that arr is not modified.
I've been practicing some algorithms with ruby for a while, and I'm wondering if it is possible to catch the returned value from within the method.
the code below is to reverse a string without any kind of reverse method and with few local variables...
def rev(a)
i = -1
a.split("").each do |el|
el[0] = a[i]
i = i + (-1)
end.join
end
Note that the result of the 'each' method is not being assigned to any variable. So, 'each' evaluates to an array with a reversed sequence of characters. At the 'end' (literally) I've just 'called' the method 'join' to glue everything together. The idea is to 'catch' the returned value from all this process and check if is true or false that the reversed string is a palindrome.
If the reversed string is equal to the original one then the word is a palindrome. Ex. "abba", "sexes", "radar"...
for example:
def rev(a)
i = -1
a.split("").each do |el|
el[0] = a[i]
i = i + (-1)
end.join
# catch here the returned value from the code above
# and check if its a palindrome or not. (true or false)
end
Thank you guys! I will be very grateful if anyone could help me figure out this!
Just add == a to see if your reversal matches the original string:
def rev(a)
i = -1
a.split("").each do |el|
el[0] = a[i]
i = i + (-1)
end.join == a
end
puts rev("racecar") # => true
puts rev("racecars") # => false
An easier way to check palindromes (rev could be better named palindrome?) is a == a.reverse since .reverse is essentially what your split/each/join does.
If you want back all the information, you can return an array with both the values:
def rev(a)
i = -1
rev = a.split("").each do |el|
el[0] = a[i]
i = i + (-1)
end.join
[rev, rev == a] # or
# return rev, rev == a
end
p rev("abra") #=> ["arba", false]
p rev("abba") #=> ["abba", true]
You can also return a hash:
{ reverse: rev, palindrome: rev == a}
to get
#=> {:reverse=>"arba", :palindrome=>false}
#=> {:reverse=>"abba", :palindrome=>true}
Here are a couple of other ways you could reverse a string.
#1
def esrever(str)
s = str.dup
(str.size/2).times { |i| s[i], s[-1-i] = s[-1-i], s[i] }
s
end
esrever("abcdefg")
#=> "gfedcba"
esrever("racecar")
#=> "racecar"
This uses parallel assignment (sometimes called multiple assignment).
#2
def esrever(str)
a = str.chars
''.tap { |s| str.size.times { s << a.pop } }
end
esrever("abcdefg")
#=> "gfedcba"
esrever("racecar")
#=> "racecar"
I've used Object#tap merely to avoid creating a local variable initialized to an empty string and then having to make that variable the last line of the method.
With both methods a string str is a palindrome if and only if str == esrever(str).
How I could replaces a string like this
I think something like this
inputx.gsub(/variable1/,string1.split(";")[i])
But I dont know How I could do this code
name1;variable1
name;variable1
name3;variable1
by
dog;watch;rock
For obtain this
name1;dog
name;watch
name3;rock
string1 => dog;watch;rock ; this string Im trying to split for replace each string variable1
Please help me
subst = "dog;watch;rock".split ';'
input.gsub(/variable1/) do subst.shift end
#⇒ "name1;dog \n name;watch \n name3;rock"
Given (assuming) this input:
inputx = <<-EOD
name1;variable1
name;variable1
name3;variable1
EOD
#=> "name1;variable1\nname;variable1\nname3;variable1\n"
string1 = 'dog;watch;rock'
#=> "dog;watch;rock"
You can chain gsub and with_index to perform a replacement based on its index:
inputx.gsub('variable1').with_index { |_, i| string1.split(';')[i] }
#=> "name1;dog\nname;watch\nname3;rock\n"
You could also perform the split beforehand:
values = string1.split(';')
#=> ["dog", "watch", "rock"]
inputx.gsub('variable1').with_index { |_, i| values[i] }
#=> "name1;dog\nname;watch\nname3;rock\n"
I'm not sure there's a way to do it using .gsub(). One simple way to achieve what you want to is the following:
str = "dog;watch;rock"
array = str.split(";")
array.each_with_index do |str, i|
array[i] = "name#{i + 1};#{str}"
end
puts array
Output:
name1;dog
name2;watch
name3;rock
file intro2 => dog;watch;rock
file intro
name1;variable1
name;variable1
name3;variable1
ruby code
ruby -e ' n=0; input3= File.read("intro");string1= File.read("intro2") ;input3x=input3.gsub("variable1") { val =string1.split(";")[n].to_s; n+=1; val } ;print input3x' >gggf
I want to split a string by colon.
This is an example of input:
str = "one[two:[three::four][five::six]]:seven:eight[nine:ten]"
This is an example of output:
array = ["one[two:[three::four][five::six]]", "seven", "eight[nine:ten]"]
The aim is to understand the regex representing the colon outside parentheses and nested parentheses.
But there are some constraints:
The template of regex must be like this: ^(.+)<colon_regex>(.*)<colon_regex>(.*)$
The match must be unique, with three groups.
Can you give me a suggestion?
You can use a very simple regex:
SUB_CHAR = 0.chr
#=> "\x00"
r = /#{SUB_CHAR}/
#=> /\x00/
to be used in s.split(r).
There is of course a catch: you must modify the string you pass to Puppet, (along with the above regex).
str = "one[two:[three::four][five::six]]:seven:eight[nine:ten]"
count = 0
idx = str.size.times.with_object([]) do |i,a|
case str[i]
when '[' then count += 1
when ']' then count -= 1
when ':' then a << i if count.zero?
end
end
#=> [33, 39]
s = str.dup
#=> "one[two:[three::four][five::six]]:seven:eight[nine:ten]"
idx.each { |i| s[i] = SUB_CHAR }
s #=> "one[two:[three::four][five::six]]\u0000seven\u0000eight[nine:ten]"
s.split(r)
#=> ["one[two:[three::four][five::six]]", "seven", "eight[nine:ten]"]
Adapting this nested parenthesis regex, you can do:
txt="one[two:[three::four][five::six]]:seven:eight[nine:ten]"
pat=Regexp.new('((?>[^:\[]+|(\[(?>[^\[\]]+|\g<-1>)*\]))+)')
puts txt.scan(pat).map &:first
one[two:[three::four][five::six]]
seven
eight[nine:ten]
I have a String and I want to get another string out of it which has only characters at odd occuring positions.
For example if i have a string called ABCDEFGH, the output I expect is ACEG since the character indexes are at 0,2,4,6 respectively. I did it using a loop, but there should be one line implementation in Ruby (perhaps using Regex?).
>> "ABCDEFGH".gsub /(.)./,'\1'
=> "ACEG"
Here is one-line solution:
"BLAHBLAH".split('').enum_for(:each_with_index).find_all { |c, i| i % 2 == 0 }.collect(&:first).join
Or:
''.tap do |res|
'BLAHBLAH'.split('').each_with_index do |char, index|
res << c if i % 2 == 0
end
end
One more variant:
"BLAHBLAH".split('').enum_slice(2).collect(&:first).join
Some other ways:
Using Enumerable methods
"BLAHBLAHBLAH".each_char.each_slice(2).map(&:first).join
Using regular expressions:
"BLAHBLAHBLAH".scan(/(.).?/).join
Not sure about the run-time speed but it's one line of processing.
res = "";
"BLAHBLAH".scan(/(.)(.)/) {|a,b| res += a}
res # "BABA"
(0..string.length).each_with_index { |x,i| puts string[x] if i%2 != 0 }