How to sum up third elements of string in array [closed] - ruby-on-rails

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 months ago.
Improve this question
I have the following output:
["1154,1,8.00", "1162,1,8.00", "1161,1,8.00"]
I would like to sum the third element of each item: 8.00 + 8.00 + 8.00
I've tried with .last, .map with no luck.
What is the best way of doing this?

You can do it like this:
["1154,1,8.00", "1162,1,8.00", "1161,1,8.00"].sum { |x| x.split(',').last.to_f }
# output
# => 24.0

arr = ["1154,1,8.00", "1162,1,8.00", "1161,1,8.00"]
rgx = /(?<=,)(?:0|[1-9]\d*)\.\d{2}\z/
arr.sum { |s| s[rgx].to_f }
#=> 24.0
The regular expression can be broken down as follows.
/
(?<=,) # positive lookbehind asserts previous character is ','
(?: # begin non-capture group
0 # match '0'
| # or
[1-9] # match a digit other than '0'
\d* # match zero or more digits
) # end non-capture group
\. # match '.'
\d{2} # match two digits
\z # match end of string
/

Related

Rails string split every other "."

I have a bunch of sentences that I want to break into an array. Right now, I'm splitting every time \n appears in the string.
#chapters = #script.split('\n')
What I'd like to do is .split ever OTHER "." in the string. Is that possible in Ruby?
You could do it with a regex, but I'd start with a simple approach: just split on periods, then join pairs of substrings:
s = "foo. bar foo. foo bar. boo far baz. bizzle"
s.split(".").each_slice(2).map {|p| p.join "." }
# => => ["foo. bar foo", " foo bar. boo far baz", " bizzle"]
This is a case where it's easier to use String#scan than String#split.
We can use the following regular expression:
r = /(?<=\.|\A)[^.]*\.[^.]*(?=\.|\z)/
str=<<~_
Now is the time. This is it. It is now. The time to have fun.
The time to make new friends. The time to party.
_
str.scan(r)
#=> [
# "Now is the time. This is it",
# " It is now. The time to have fun",
# "\nThe time to make new friends. The time to party"
#=> ]
We can write the regular expression in free-spacing mode to make it self-documenting.
r = /
(?<= # begin a positive lookbehind
\A # match the beginning of the string
| # or
\. # match a period
) # end positive lookbehind
[^.]* # match zero or more characters other than periods
\. # match a period
[^.]* # match zero or more characters other than periods
(?= # begin a positive lookahead
\. # match a period
| # or
\z # match the end of the string
) # end positive lookahead
/x # invoke free-spacing regex definition mode
Note that (?<=\.|\A) can be replaced with (?<![^\.]). (?<![^\.]) is a negative lookbehind that asserts the match is not preceded by a character other than a period.
Similarly, (?=\.|\z) can be replaced with (?![^.]). (?![^.]) is a negative lookahead that asserts the match is not followed by a character other than a period.

Regex to separate IIF clauses in groups

I am trying to get a regex that separates the parts of a IIF made in VB to convert it to a RoR if. The string that I am trying to convert is this one:
Var007>2,IIF(Var133=2 OR Var133=3,'',Var132+IIF(Var123=2,Var122+IIF(Var113=2,Var112,0),0)+IIF(Var007>3,IIF(Var143=3,Var142,0),0)),''
And the regex that I am developing is this one:
(.{1,}),(?![^\(]*\))(.{1,}),(?![^\(]*\))(.{1,})
I want to get this:
Var007>2
IIF(Var133=2 OR Var133=3,'',Var132+IIF(Var123=2,Var122+IIF(Var113=2,Var112,0),0)+IIF(Var007>3,IIF(Var143=3,Var142,0),0))
Now , I am getting this because canĀ“t select a group between brackets.
Var007>2,IIF(Var133=2 OR Var133=3,'',Var132+IIF(Var123=2,Var122+IIF(Var113=2,Var112,0),0)+IIF(Var007>3
IIF(Var143=3,Var142,0),0))
You can see it on Rubular.
This are a few examples of the possible string:
Var007>0,IIF(Var002=0,0, ((Var111*Var112)*CaracteristicaArticulo('Var002','Kilos M2')*(1+(CaracteristicaArticulo('Var002','Porcentaje Rozamiento')/100)))+IIF(Var022=1,Var112*0.800,0)+(Var112*0.339)),''
Var007>1,IIF(Var110=0,IIF(Var025=0 OR Var025=1 OR Var025=39 OR Var025=2,20,IIF(Var025=3 OR Var025=4,21,IIF(Var025=5 OR Var025=6 OR Var025=28 OR Var025=29,22,IIF(Var025=7 OR Var025=8 OR Var025=9 OR Var025=10,24,IIF(Var025=12,26,IIF(Var025=11 OR Var025=14 OR Var025=16 OR Var025=17,27,' ')))))),''),''
There won't be single quotes inside string literals.
Please I need your help ;)
It is generally not a good idea to parse strings like this with regex, but your requirements are not that complex in this case.
Here is a solution that will match "tokens" that consist of 1 or more occurrences of 1+ word chars followed with a balanced amount of (...) and having '...' substrings inside (with possible ( or )), or chars other than ,:
s = "Var007>2,IIF(Var133=2 OR Var133=3,'',Var132+IIF(Var123=2,Var122+IIF(Var113=2,Var112,0),0)+IIF(Var007>3,IIF(Var143=3,Var142,0),0)),''"
rx = /
( # Group 1, what we need to extract
(?: # A non-capturing group acting as a container
\w+ # 1 or more word chars
( # Group 2 (technical one)
\( # opening parenthesis
(?:
'[^']*' # a single quoted substring with no single quotes inside
| # or
[^()']+ # 1 or more chars other than quote and parentheses
| # or
\g<2> # recurse Group 2 pattern
)* # Group 2 end, can repeat 0 or more times
\) # closing parenthesis
)
|
[^,] # Any char other than a comma
)+ # One or more occurrences of the alternatives in the container group
) # End of Group 1
/x # extended mode with all in-pattern whitespace ignored
res = []
s.scan(rx) { |m|
res << m[0] # Only collect Group 1 values dropping all others
}
puts res
See the Ruby demo online
Output:
Var007>2
IIF(Var133=2 OR Var133=3,'',Var132+IIF(Var123=2,Var122+IIF(Var113=2,Var112,0),0)+IIF(Var007>3,IIF(Var143=3,Var142,0),0))
''

Can we override operators in Ruby? [closed]

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 7 years ago.
Improve this question
in a case...such as
(10 + 20) * 10
=> 300
the expression fragment enclosed in parentheses is evaluated before the higher precedence multiplication.So does it applies to other operators as well.Can i override other operators such as << !...etc
When humans evaluate expressions, they usually do so starting at the left of the expression and working towards the right. For example, working from left to right we get a result of 300 from the following expression:
10 + 20 * 10 = 300
This is because we, as humans, add 10 to 20, resulting in 30 and then multiply that by 10 to arrive at 300. Ask Ruby to perform the same calculation and you get a very different answer:
> 10 + 20 * 10
=> 210
This is a direct result of operator precedence. Ruby has a set of rules that tell it in which order operators should be evaluated in an expression. Clearly, Ruby considers the multiplication operator (*) to be of a higher precedence than the addition (+) operator.
Overriding Operator Precedence
The precedence built into Ruby can be overridden by surrounding the lower priority section of an expression with parentheses. For example:
> (10 + 20) * 10
=> 300
In the above example, the expression fragment enclosed in parentheses is evaluated before the higher precedence multiplication.
for more info refer this :
http://rubysnippets.com/2013/01/25/operator-overloading-in-ruby/
Override == operator in Ruby
I hope this makes you clear to understand :)
yes you can,you can do it like this
class String
def << str
self + "*" + str
end
end
puts "str" << "sss"

what does _? mean in the following regex? [duplicate]

This question already has an answer here:
Reference - What does this regex mean?
(1 answer)
Closed 8 years ago.
What does _? mean in the following rails regex?
/\A_?[a-z]_?(?:[a-z0-9.-]_?)*\z/i
I have attempted to decipher the regex as follows
# regex explained
# \A : matches the beginning of the string
# _? :
# [ : beginning of character group
# a-z : any lowercase letter
# ] : end of character group
# _? :
# ( : is a capture group, anything matched within the parens is saved for later use
# ?: : non-capturing group: matches below, but doesn't store a back-ref
# [ : beginning of character group
# a-z : any lowercase letter
# A-Z : any uppercase letter
# 0-9 : any digit
# . : a fullstop or "any character" ??????
# _ : an underscore
# ] : end of character group
# _? :
# ) : See above
# * : zero or more times of the given characters
# \z : is the end of the string
_ matches an underscore.
? matches zero or one of the preceeding character; basically making the preceeding character optional.
So _? will match one underscore if it is present, and will match without it.
? means that the previous expression should appear 0 or 1 times, similarly to how * means it should match 0 or more times, or + means it should match 1 or more times.
So, for example, with the RE /\A_?[A-Z]?\z/, the following strings will match:
_O
_
P
but these will not:
____
A_
PP
The RE you posted originally states:
The string may begin with an underscore
Then there must be a lowercase letter
Then there may be another underscore
For the rest of the string, there must be a letter, number, period, or -, which may be followed by an underscore
Example strings that match this RE:
_a_abcdefg
b_abc_def_
_qasdf_poiu_
a12345_
z._.._...._......_
u
_? means _ is optional.
It can accept _sadasd_sadsadsa_asdasdasd_ or asdasdsadasdasd i.e _ separated strings where _ is optional.
See demo.
http://regex101.com/r/hQ1rP0/89

Regex for distinct words (not embedded in other words)

How can I create a regular expression to match distinct words?
I tried the following regex, but it also matches words embedded in other words:
#"(abs|acos|acosh|asin|asinh|atan|atanh)"
For example, with
#"xxxabs abs"
abs by itself should match, but not inside xxxabs.
Although the solution (word boundaries) is an old classic, yours is an interesting question because the words in the alternation are so similar.
You can start with this:
\b(?:abs|acos|acosh|asin|asinh|atan|atanh)\b
And compress to that:
\b(?:a(?:cosh?|sinh?|tanh?|bs))\b
How does it work?
The key idea is to use the word boundaries \b to ensure that the match is not embedded in a larger word.
The idea of the compression is to make the engine match faster. It's hard to read, though, so unless you need every last drop of performance, that's purely for entertainment purposes.
Token-By-Token
\b # the boundary between a word char (\w) and
# something that is not a word char
(?: # group, but do not capture:
a # 'a'
(?: # group, but do not capture:
cos # 'cos'
h? # 'h' (optional (matching the most
# amount possible))
| # OR
sin # 'sin'
h? # 'h' (optional (matching the most
# amount possible))
| # OR
tan # 'tan'
h? # 'h' (optional (matching the most
# amount possible))
| # OR
bs # 'bs'
) # end of grouping
) # end of grouping
\b # the boundary between a word char (\w) and
# something that is not a word char
Bonus Regex
In case you're feeling depressed today, this alternate compression (is it longer than the original?) should cheer you up.
\b(?:a(?:(?:co|b)s|(?:cos|(?:si|ta)n)h|(?:si|ta)n))\b

Resources