(ruby 2.5.3)
When you want to rotate a JavaScript iterative statement while making changes to array elements
for (var i = 0; i < A.length; i++){
// Omitted: Change the value of A [i] under certain conditions
}
If you want to reproduce in Ruby in the same atmosphere
A.each_index do |i|
## Omitted: Change the value of A [i] under certain conditions
end
I will write.
I was rewriting my private code written in JavaScript into Ruby. The following JavaScript function is a part of it, and when English parts are passed in an array, the beginning of the word corresponding to the beginning of the sentence is changed to uppercase by the symbol at the end and combined and output.
function Upcasing(result_lines) {
result_lines[0] = result_lines[0].replace(/^[a-z]/, result_lines[0].charAt(0).toUpperCase() );
var break_flg = false;
const break_sign = { ".":true, "!":true, "?":true, ",":false };
for (var i = 0; i < result_lines.length; i++) {
if (break_flg === true) {
result_lines[i] = result_lines[i].replace(/^[a-z]/, result_lines[i].charAt(0).toUpperCase() );
}
if ( break_sign[result_lines[i].slice(-1)] === true) {
break_flg = true;
} else {
break_flg = false;
}
}
return result_lines.join(" ");
}
console.log(Upcasing(["oh,", "yeah!", "hello!"]));
// Execution result
// Oh, yeah! Hello!
// <= What was "hello!" Is capitalized at the beginning of the next word due to the previous "!"
The following is what I rewrote (I thought) to the Ruby method as it is.
def Upcasing(result_lines)
result_lines[0] = result_lines[0].capitalize
break_flg = false
break_sign = { "."=>true, "!"=>true, "?"=>true, ","=>false }
for r in result_lines
if break_flg == true
r = r.capitalize
end
if break_sign[r.slice(-1)] == true
break_flg = true
else
break_flg = false
end
end
joined_line = result_lines.join(" ")
return joined_line
end
print Upcasing(["oh,", "yeah!", "hello!"])
## Execution result
## Oh, yeah! hello! <= "H" in "hello!" Is not capitalized
Since the for expression
does not create a scope like the ```each method , the
rof the
for r in result_linescan be used outside the block, but in the first place it is with the original array element. Is a newly defined variable, so if you want to make changes to the array elements, you need to manipulate
results_lines [i] even inside the block. (This variable
r`` is not a block parameter.)
Usually, when writing Ruby code, there are not many scenes where values are assigned in repeating blocks, so the concept of temporary boxes such as block parameters and recognition of the generated scope are lacking. It was.
-Control Structure> for | Ruby 2.7.0 Reference Manual
-Method call with block | Ruby 2.7.0 Reference Manual
-module Enumerable | Ruby 2.7.0 Reference Manual
(* The one used in this memorandum is ruby 2.5.3.)
In the form of for variable name in array name
like the above code, the index for specifying the array element in the block is not defined in the variable, so use the `ʻeach_index method`` and use the following Changed to.
(The code below was refactored in an article posted at a later date.)
def Upcasing(result_lines)
result_lines[0] = result_lines[0].capitalize
break_flg = false
break_sign = { "."=>true, "!"=>true, "?"=>true, ","=>false }
result_lines.each_index do |i|
if break_flg == true
result_lines[i] = result_lines[i].capitalize
end
if break_sign[result_lines[i].slice(-1)] == true
break_flg = true
else
break_flg = false
end
end
joined_line = result_lines.join(" ")
return joined_line
end
print Upcasing(["oh,", "yeah!", "hello!"])
## Execution result
Oh, yeah! Hello!
(For this time, since there is no need to use the variable defined in the repeating block outside, there is no effect on the whole depending on whether the scope is generated by for expression
or ```each method ``. .)
I think that omitting the variable name and reducing the amount of sentences is a big advantage of using block parameters, but if the array element is changed in the iterative process, it may not be used much.
I thought about passing the value and index to the block parameter with the ʻeach_with_index method
as shown in the draft below and using it only in the part that refers to the current element, but I feel that mistakes may increase. And stopped.
The variable name is| r |Not| current_element |It may still be easy to understand.
result_lines.each_with_index do |current_element, i|
if break_flg == true
result_lines[i] = current_element.capitalize
end
if break_sign[current_element.slice(-1)] == true
break_flg = true
else
break_flg = false
end
end
-each_with_index (* args)-> Enumerator | Ruby 2.7.0 Reference Manual
Recommended Posts