I would like to break a long word in my Ruby on Rails string (something like <wbr> in HTML).
Is it possible to tell Ruby to add character x in string y each z characters?
Try
result = subject.gsub(/(.{10})/m, '\1XX')
substituting the number you want for 10 and the replacement string you want for XX
In Perl it would be somewhere along the lines of s/(\w{42})/$1\n/g
I'm not familiar with rails, but in pure ruby you can always write your own. No idea the amount of speed you give up for something like this if any.
def addcharacter(num, char, string)
x = 0
resultstring = ""
string.each_byte do |byte|
resultstring << byte.chr
x += 1
if x == num
resultstring << char
x = 0
end
end
return resultstring
end
mystring = "hello there"
a = addcharacter(2,"*",mystring)
puts a
If your original string is str = "0123456789abcde" and you want:
01234XXX56789XXXabcdeXXX :: use str.gsub(/.{5}/, '\&XXX')
01234XXX56789XXXabcde :: use str.scan(/.{5}/).join('XXX')
These will produce slightly different input for str = "012345678abcdef"
01234XXX56789XXXabcdeXXXf :: from str.gsub(/.{5}/, '\&XXX')
01234XXX56789XXXabcde :: from str.scan(/.{5}/).join('XXX')
01234XXX56789XXXabcdeXXXfXXX :: from str.gsub(/.{1,5}/, '\&XXX')
01234XXX56789XXXabcdeXXXf :: from str.scan(/.{1,5}/).join('XXX')
One can use a regular expression without a back-reference.
Let's add 'XX' to 'My dog has fleas' every n = 3 characters:
'My dog has fleas'.gsub(/.{#{n}}\K/, 'XX')
#=> "My XXdogXX haXXs fXXleaXXs"
The regular expression reads, "match n characters and then (\K) discard all previous matches and reset the regex's string pointer to the current location (just after those n characters and before the next character)".
For the example given the string pointer is initially at the beginning of the string. .{3} matches the first three characters of the string, 'My '. \K discards that match and resets the string pointer to the (zero-width) location between the third and fourth characters, ' ' and 'd'. gsub replaces that zero-width match with 'XX' and the string pointer remains before 'd'. The next match is 'dog', \K discards that match and resets the string pointer, the zero-width location between 'g' and ' ', which is replaced with 'XX' and so on.
Related
I am busy working through some problems I have found on the net and I feel like this should be simple but I am really struggling.
Say you have the string 'AbcDeFg' and the next string of 'HijKgLMnn', I want to be able to find the same characters in the string so in this case it would be 'g'.
Perhaps I wasn't giving enough information - I am doing Advent of Code and I am on day 3. I just need help with the first bit which is where you are given a string of characters - you have to split the characters in half and then compare the 2 strings. You basically have to get the common character between the two. This is what I currently have:
file_data = File.read('Day_3_task1.txt')
arr = file_data.split("\n")
finals = []
arr.each do |x|
len = x.length
divided_by_two = len / 2
second = x.slice!(divided_by_two..len).split('')
first = x.split('')
count = 0
(0..len).each do |z|
first.each do |y|
if y == second[count]
finals.push(y)
end
end
count += 1
end
end
finals = finals.uniq
Hope that helps in terms of clarity :)
Did you try to convert both strings to arrays with the String#char method and find the intersection of those arrays?
Like this:
string_one = 'AbcDeFg'.chars
string_two = 'HijKgLMnn'.chars
string_one & string_two # => ["g"]
One way to do that is to use the method String#scan with the regular expression
rgx = /(.)(?!.*\1.*_)(?=.*_.*\1)/
I'm not advocating this approach. I merely thought some readers might find it interesting.
Suppose
str1 = 'AbcDgeFg'
str2 = 'HijKgLMnbn'
Now form the string
str = "#{str1}_#{str2}"
#=> "AbcDeFg_HijKgLMnbn"
I've assumed the strings contain letters only, in which case they are separated in str with any character other than a letter. I've used an underscore. Naturally, if the strings could contain underscores a different separator would have to be used.
We then compute
str.scan(rgx).flatten
#=> ["b", "g"]
Array#flatten is needed because
str.scan(rgx)
#=>[["b"], ["g"]]
The regular expression can be written in free-spacing mode to make it self-documenting:
rgx =
/
(.) # match any character, same to capture group 1
(?! # begin a negative lookahead
.* # match zero or more characters
\1 # match the contents of capture group 1
.* # match zero or more characters
_ # match an underscore
) # end the negative lookahead
(?= # begin a positive lookahead
.* # match zero or more characters
_ # match an underscore
.* # match zero or more characters
\1 # match the contents of capture group 1
) # end the positive lookahead
/x # invoke free-spacing regex definition mode
Note that if a character appears more than once in str1 and at least once in str2 the negative lookahead ensures that only the last one in str1 is matched, to avoid returning duplicates.
Alternatively, one could write
str.gsub(rgx).to_a
The uses the (fourth) form of String#gsub which takes a single argument and no block and returns an enumerator.
Hi I try to separate input like this : <Text1><Text2><Text2>..<TextN>
in a array who only have each text in each index, how I can use split with double parameters?
I try make a double split but doesn't work:
request = client.gets.chomp
dev = request.split("<")
split_doble(dev)
dev.each do |devo|
puts devo
end
def split_doble (str1)
str1.each do |str2|
str2.split(">")
end
end
When you have a string like this
string = "<text1><text2><textN>"
then you can extract the text between the < and > chars like that:
string.scan(/\w+/)
#=> ["text1", "text2", "textN"]
/\w+/ is a regular expression that matches a sequence of word characters (letter, number, underscore) and therefore ignores the < and > characters.
Also see docs about String#scan.
In the string "<text1><text2><textN>" the leading < and ending > are in the way, so get rid of them by slicing them off. Then just split on "><".
str = "<text1><text2><textN>"
p str[1..-2].split("><") # => ["text1", "text2", "textN"]
The one exception is that the returned string cannot begin or end with a hyphen, and each odd digit is permitted only a single hyphen before and after each odd digit. For example:
def hyphenate(number)
# code
end
hyphenate(132237847) # should return "1-3-22-3-7-84-7"
"-1-3-22-3-7-84-7-" # incorrect because there is a hyphen before and after
# each beginning and ending odd digit respectively.
"1--3-22-3--7-84-7" # Also incorrect because there is more than one
# single hyphen before and after each odd digit
I suggest to match a non-word boundary \B (that will match a position between two digits) followed or preceded with an odd digit:
number.to_s.gsub(/\B(?=[13579])|\B(?<=[13579])/, '-')
Since the same position can't be matched twice, you avoid the problem of consecutive hyphens.
rubular demo
with the replacement
A simple way is to convert the number to a string, String#split the string on odd digits (using a group so that the odd digit delimiters get into the output), clean up the stray '' strings that String#split will produce, and put it back together with Array#join:
number.to_s.split(/([13579])/).reject(&:empty?).join('-')
def hyphenate(number)
test_string = ''
# Convert the number to a string then iterate over each character
number.to_s.each_char do |n|
# If the number is divisible by 2 then just add it to the string
# else it is an odd number then add it with the hyphens
n.to_i % 2 == 0 ? test_string += n : test_string += "-#{n}-"
end
# Remove the first character of the string if it is a hyphen
test_string = test_string[1..-1] if test_string.start_with?('-')
# Remove the last character of the string if it is a hyphen
test_string = test_string[0..-2] if test_string.end_with?('-')
# Return the string and replace all double hyphens with a single hyphen
test_string.gsub('--', '-')
end
puts hyphenate(132237847)
Returns "1-3-22-3-7-84-7"
Here's another approach for taking a number and returning it in string form with its odd digits surrounded by hyphens:
def hyphenate(number)
result = ""
number.digits.reverse.each do |digit|
result << (digit.odd? ? "-#{digit}-" : digit.to_s)
end
result.gsub("--", "-").gsub(/(^-|-$)/, "")
end
hyphenate(132237847)
# => "1-3-22-3-7-84-7"
Hope it helps!
I am trying to do this test and there are bunch of solutions online and here but I first want to figure out why my solution is wrong even though it seems that it puts right results when I enter certain strings :
Here is what they are asking :
Write a method that takes in a string. Return the longest word in the
string. You may assume that the string contains only letters and
spaces.
You may use the String split method to aid you in your quest.
Here is my solution where I thought I could turn string into array, sort it from max length descending and then just print first element in that new string like this :
def longest_word(sentence)
sentence = sentence.split
sentence.sort_by! { |longest| -longest.length }
return sentence[0]
end
That doesn't seem to work obviously since their test gives me all false..here is the test :
puts("\nTests for #longest_word")
puts("===============================================")
puts(
'longest_word("short longest") == "longest": ' +
(longest_word('short longest') == 'longest').to_s
)
puts(
'longest_word("one") == "one": ' +
(longest_word('one') == 'one').to_s
)
puts(
'longest_word("abc def abcde") == "abcde": ' +
(longest_word('abc def abcde') == 'abcde').to_s
)
puts("===============================================")
So the question is why? And can I just fix my code or the idea is all wrong and I need to do it completely different?
str = "Which word in this string is longest?"
r = /[[:alpha:]]+/
str.scan(r).max_by(&:length)
#=> "longest"
This regular expression reads, "match one or more characters". The outer brackets constitute a character class, meaning one of the characters within the brackets must be matched.
To deal with words that are hyphenated or contain single quotes, the following is an imperfect modification1:
str = "Who said that chicken is finger-licken' good?"
r = /[[[:alpha:]]'-]+/
str.scan(r).max_by(&:length)
#=> "finger-licken'"
This regular expression reads, "match one or more characters that are a letter, apostrophe or hyphen". The outer brackets constitute a character class, meaning one of the characters within the brackets must be matched.
1 I've successfully used "finger-licken'" in scrabble.
I'd write it something like:
str = "Write a method that takes in a string"
str.split.sort_by(&:length).last # => "string"
I have a string of text:
string = "%hello %world ho%w is i%t goin%g"
I want to return the following:
"Hello World hoW is iT goinG
The % sign is a key that tells me the next character should be capitalized. The closest I have gotten so far is:
#thing = "%this is a %test this is %only a %test"
if #thing.include?('%')
indicator_position = #thing.index("%")
lowercase_letter_position = indicator_position + 1
lowercase_letter = #thing[lowercase_letter_position]
#thing.gsub!("%#{lowercase_letter}","#{lowercase_letter.upcase}")
end
This returns:
"This is a Test this is %only a Test"
It looks like I need to iterate through the string to make it work as it is only replacing the lowercase 't' but I can't get it to work.
You can do this with gsub and a block:
string.gsub(/%(.)/) do |m|
m[1].upcase
end
Using a block allows you to run arbitrary code on each match.
Inferior to #tadman, but you could write:
string.gsub(/%./, &:upcase).delete('%')
#=> "Hello World hoW is iT goinG