how to remove a second AMPERSAND in a string? - ruby-on-rails

1.how to remove second AMPERSAND from following string?
"apple&banana&grape&apple"
2.how to split the string at second AMPERSAND for following string? I want to ignore the first AMPERSAND and split from second AMPERSAND onwards.
"apple&banana&grape&apple"

arr = "apple&banana&grape&apple".split('&')
#arr = ["apple", "banana", "grape", "apple"]
To solve first query,
arr[0..1].join('&').concat(arr[2..-1].join('&'))
# "apple&bananagrape&apple"
For second query,
[words[0..1].join('&'), words[2..-1]].flatten
#["apple&banana", "grape", "apple"]

You can use gsub with a block:
For your first case:
index_to_remove = 2
current_index = 0
my_string = "apple&banana&grape&apple"
my_string.gsub('&') { |x| current_index += 1; current_index == index_to_remove ? '' : x}
#=> "apple&bananagrape&apple"
For your second case, you can replace the second & with a unique value and split on that:
index_to_split = 2
current_index = 0
my_string = "apple&banana&grape&apple"
my_string.gsub!('&') { |x| current_index += 1; current_index == index_to_split ? '&&' : x}
my_string.split('&&')
#=> ["apple&banana", "grape&apple"]

If you split the string by the &, it's quite simple to rejoin the first two / last two and convert back into a string or array:
words = "apple&banana&grape&apple".split('&')
# First query
words[0..1].join('&') + words[2..-1].join('&')
# Giving you: "apple&bananagrape&apple"
# Second query
[words[0..1].join('&'), words[2..-1].join('&')]
# Giving you: ["apple&banana", "grape&apple"]
You could tweak this for different length strings and separators as needed.
I imagine there's a good solution using regex matchers, but I'm not too hot on them, so hope this helps in some way!

Related

Creating Random Strinngs in Ruby with at least one sepcial character, one digit, one upper-case, one lowercase with no characters repeated in Ruby

My task is to generate a random string with following parameters:
At least one Uppercase
At least one lower
At least one digit
No repeated chars/digits allowed ( e.g. aa not allowed, aba is allowed, Aa is allowed)
I'm able to generate a random string with 1,2,3 parameters but parameter 4 logic is missing.
inputChars = [('a'..'z'), ('A'..'Z'),(0..9)].map(&:to_a).flatten
string = (0...16).map { inputChars[rand(inputChars.length)] }.join
require 'set'
inputChars = [('a'..'z'), ('A'..'Z'),(0..9)].map(&:to_a).flatten
set_string = Set.new
loop do
break if set_string.size == 16
cr = inputChars[rand(inputChars.length)]
set_string << cr
end
output = set_string.to_a.join
i just change your map operation to loop operation and add Set data structure to store the character from random inputChars operation. Using Set will not allow same character
Let's begin by defining two constants.
CHARS_BY_TYPE = {
lower: ('a'..'z').to_a.freeze,
upper: ('A'..'Z').to_a.freeze,
digit: ('0'..'9').to_a.freeze
}.freeze
ALL = (CHARS_BY_TYPE[:lower] + CHARS_BY_TYPE[:upper] + CHARS_BY_TYPE[:digit]).freeze
#=> [["a", "b",..., "z", "A", "B",..., "Z", "0", "1",..., "9"]
I will initially build a string of a specified length by randomly selecting one character at a time from the array ALL, ensuring that no two consecutive characters are the same. There is no assurance, however, that the resulting string will contain at least one uppercase letter, one lowercase letter and one digit.
def append_random_char(last_char)
loop do
ch = ALL.sample
break ch unless ch == last_char
end
end
Our main method will begin as follows:
def random_string(str_len)
raise ArgumentError if str_len < 3
(str_len - 2).times.with_object('') { |_,s| s << append_random_char(s[-1]) }
# ...
end
For example:
s = random_string(40)
#=> "arN64kDw6ClzcNMj8WAkj1NJC2B5oFoRlcXl5S"
str_len is the required string length, 40 in the example. Observe that s contains 38 characters of which no two successive characters are equal. We will need to add 2 characters later. If the string contained no digits, for example, at least one of those two characters added (at a random location) will be a (randomly-selected) digit. If the string were shorter and contained, for example, digits only, the two characters added will be an uppercase letter and a lowercase letter.
Next we need to see if the string is lacking an uppercase letter, a lowercase letter and/or a digit. (It cannot be missing all three, as the string must contain at least three characters.)
require 'set'
def types_to_add(str)
[:lower, :upper, :digit].select do |type|
st = CHARS_BY_TYPE[type].to_set
str.each_char.none? { |ch| st.include?(ch) }
end
end
For the random string generated above we obtain:
types_to_add(s)
#=> []
meaning that the string contains at least one uppercase letter, one lowercase letter and one digit. Try this:
types_to_add(s.gsub(/\d|[A-Z]/, '')
#=> [:upper, :digit]
See Enumerable#none?. CHARS_BY_TYPE[type] is converted to a set merely to speed look-ups.
Suppose now we need to insert an uppercase letter, lowercase letter or digit to satisfy the requirement that there is at least one of each in the string. Specifically, we wish to insert a randomly-drawn character (from CHARS_BY_TYPE[:lower], CHARS_BY_TYPE[:upper] or CHARS_BY_TYPE[:digit]) at a random location in the string we are constructing, with the restriction that neither the preceding nor following character is the same character.
def insert_in_string(str, ch)
i = loop do
i = rand(str.size + 1)
next if ch == str[i]
break i if i.zero? || ch != str[i-1]
end
str.insert(i, ch)
end
For example, if we were to insert the character '0' into (a copy of) our string s (which is not needed):
insert_in_string(s.dup, '0')
#=> "arN64kDw6ClzcN0Mj8WAkj1NJC2B5oFoRlcXl5S"
s #=> "arN64kDw6ClzcNMj8WAkj1NJC2B5oFoRlcXl5S"
^
This inserts the character ch before the character in str at index i. If rand(str.size + 1) returns str.size ch is inserted after the last character of str.
Following this operation the final step is to use the method append_random_char to build the string out to the desired length.
The completed main method is as follows.
def random_string(str_len)
raise ArgumentError if str_len < 3
s = (str_len - 2).times.with_object('') { |_,s| s << append_random_char(s[-1]) }
types_to_add(s).each { |type| insert_in_string(s, CHARS_BY_TYPE[type].sample) }
(str_len - s.size).times { s << append_random_char(s[-1]) }
s
end
s = random_string(40)
#=> "PtQrVFZWUYFwiwRy3ySfAy42G1NT98J6cMVMaWeT"
s.match?(/[a-z]/)
#=> true
s.match?(/[A-Z]/)
#=> true
s.match?(/\d/)
#=> true
s.size
#=> 40
This is how I would do it (warning: Not tested. Just want to present the idea
for my algorithm). I first take a random number for the length of the resulting random string (the length will be between 4 and 16 characters). Then I determine
randomly, how many of them are upper case / lower case / digits, and based on
these decision, I generate the string, ensuring that I don't get any duplicates
in succession.
uchars=('A'..'Z').to_a
lchars=('a'..'z').to_a
dchars=('0'..'9').to_a
charmap = { u: uchars, l: lchars, d: dchars }
total_length=rand(13)+4 # Total length of string to be generated
total_u=rand(total_length-3)+1 # Total number of uchars to be generated
total_l=rand(total_length-total_u-2)+1 # Total number of lchars
total_d=total_length-total_u-total_l # Total number of digits
# Array of types to generate
chartypes=([:u]*total_u + [:l]*total_l + [:d]*total_d).shuffle
# chartypes is an array similar to [:u,:d,:d,:l,:u], where the
# symbols designate the kind of character to be generated.
# outstr : random string to be generated
outstr = charmap[chartypes.first].sample
last_char = outstr.dup
total_length.times do |index|
loop do
nextchar = charmap[chartypes[index]].sample
if nextchar != last_char
outstr << nextchar
last_char = nextchar
break
end
end
end

How do I extract numbers from a string?

How would I extract every number from a string and put them in an array?
For example the string:
"\113\115\106\111\117\41\40\105\102\109\109\112\40\42"
You can use string.gmatch like this:
local my_array = {}
local my_string = "\\113\\115\\106\\111\\117\\41\\40\\105\\102\\109\\109\\112\\40\\42"
print(my_string) --note how the string is \ followed by digits
for number in string.gmatch(my_string, "\\(%d+)") do
my_array[#my_array + 1] = tonumber(number)
print(number)
end
This will get you an table with all the numbers from your string.
The \ is escaped in my example to make it equal to the string you stated.
If i misunderstood your question and the numbers you want are from the chars then you need to do
local my_array = {}
local my_string = "\113\115\106\111\117\41\40\105\102\109\109\112\40\42"
print(my_string) --note how the string is letters
for char in string.gmatch(my_string, ".") do
my_array[#my_array + 1] = string.byte(char)
print(char, my_array[#my_array])
end

How do I replace a range of characters in Ruby?

With Ruby, how do I replace a range of characters in a string? For instance, given teh string
hellothere
If I want to replace characters at index positions two through five inclusive with "#" to result in a string
he####here
How would I do this?
You could get a string range and replace it by setting the new character multiplied for the last index plus 1 less the first index:
def replace_in_string(str, replace, start, finish)
str[start..finish] = replace * (finish + 1 - start)
str
end
p replace_in_string 'hellothere', '#', 2, 5
# "he####here"

What is the most efficient way to iterate numeric string in Lua?

I have a string which consists of numbers:
str = "1234567892"
And I want to iterate individual characters in it and get indices of specific numbers (for example, "2"). As I've learned, I can use gmatch and create a special iterator to store the indices (because, as I know, I just can't get indices with gmatch):
local indices = {}
local counter = 0
for c in str:gmatch"." do
counter = counter + 1
if c == "2" then
table.insert(indices, counter)
end
end
But, I guess, this is not the most efficient decision. I also can convert string to table and iterate table, but it seems to be even more inefficient. So what is the best way to solve the task?
Simply loop over the string! You're overcomplicating it :)
local indices = {[0]={},{},{},{},{},{},{},{},{},{}} --Remove [0] = {}, if there's no chance of a 0 appearing in your string :)
local str = "26842170434179427"
local container
for i = 1,#str do
container = indices[str:sub(i, i)]
container[#container+1] = i
end
container = nil
To find all indices and also do not use regexp but just plain text search
local i = 0
while true do
i = string.find(str, '2', i+1, true)
if not i then break end
indices[#indices + 1] = i
end

Lua String Split

Hi I've got this function in JavaScript:
function blur(data) {
var trimdata = trim(data);
var dataSplit = trimdata.split(" ");
var lastWord = dataSplit.pop();
var toBlur = dataSplit.join(" ");
}
What this does is it take's a string such as "Hello my name is bob" and will return
toBlur = "Hello my name is" and lastWord = "bob"
Is there a way i can re-write this in Lua?
You could use Lua's pattern matching facilities:
function blur(data) do
return string.match(data, "^(.*)[ ][^ ]*$")
end
How does the pattern work?
^ # start matching at the beginning of the string
( # open a capturing group ... what is matched inside will be returned
.* # as many arbitrary characters as possible
) # end of capturing group
[ ] # a single literal space (you could omit the square brackets, but I think
# they increase readability
[^ ] # match anything BUT literal spaces... as many as possible
$ # marks the end of the input string
So [ ][^ ]*$ has to match the last word and the preceding space. Therefore, (.*) will return everything in front of it.
For a more direct translation of your JavaScript, first note that there is no split function in Lua. There is table.concat though, which works like join. Since you have to do the splitting manually, you'll probably use a pattern again:
function blur(data) do
local words = {}
for m in string.gmatch("[^ ]+") do
words[#words+1] = m
end
words[#words] = nil -- pops the last word
return table.concat(words, " ")
end
gmatch does not give you a table right away, but an iterator over all matches instead. So you add them to your own temporary table, and call concat on that. words[#words+1] = ... is a Lua idiom to append an element to the end of an array.

Resources