Reputation: 89
I did a small programme to count words in the array:
array = ["first line",
"second line",
"",
" fourth line containing a few more words ",
"fifth line "]
words = 0
array.each do |s|
wis = 0
s.length.times do |i|
if i == 0
if s[i] != " "
wis = 1
next #HERE IT COMES.
end
end
if s[i] != " " and s[i-1] == " "
wis += 1
end
end
words += wis
end
puts "Words in the array: #{words}"
OUTPUT:
Words in the array: 13
It works properly, but there's a one thing which I can't understand. I know that next
keyword leaves the current iteration but I don't know how it exactly works right here. If I omit it from the code, Output would be Words in the array: 14
. I know next
can be replaced with else
condition and that's the problem - I don't know how to define it.
Can you please explain me how does next
work in the code?
Can you give me the alternative solution for that if
condition without using next
keyword?
Thank you
Upvotes: 1
Views: 1184
Reputation: 196
simple example using "next" keyword
(1..10).each do |a|
next if a.even?
puts a
end
output:-
1
3
5
7
9
Usage of next in a block: When next is used within a block, it causes the block to exit immediately, returning control to the iterator method, which may then begin a new iteration by invoking the block again
Upvotes: 3
Reputation: 3723
When it comes to the use of next
, I suggest you to read this answer here.
About your code, I could tell you that learning Ruby requires a greater change in your way of programming. It is not just a matter of using Ruby syntax, but also of exploring Ruby potential to make things simple.
For instance, you could do your taks without any if
at all.
array = ["first line",
"second line",
"",
" fourth line containing a few more words ",
"fifth line "]
count = array.inject(0) { |c, item| c + item.strip.split(" ").count }
puts count
This would give you
13
which is exactly the number of words, and with no if
at all.
And this is not even close to be the best way. I'm sure this could be done even shorter.
Upvotes: 3
Reputation: 42182
Next jumps back to the beginning of the codeblock, and in this case to the next array element.
The shortest possible answer how to do this better is IMHO this
puts "Words in the array: #{array.join(' ').split(/\W+/).length}"
# Words in the array: 13
Some explanation:
While working with strings it is often best to use regular expressions, to make it easy I start with combining all array elements to one string with: array.join(' ')
The space is used as a separator to prevent that words are joined together.
This string is split again with the regular expression between the //'s, namely \W+ which means a series of non delimiter characters (thus a word).
This array is taken the length of and so giving the number of words in the string/array.
EDIT: it's two chars shorter using scan instead of split and count instead of length 8:)
array.join(' ').scan(/\W+/).count
Upvotes: 1
Reputation: 66263
As others have said, there are a lot of more elegant ways of writing a word count in Ruby. However, I'll try and answer your specific questions as there's still something to learn here.
As you've mentioned next
leaves the current iteration. In your example it means that when both the i == 0
condition and the s[i] != " "
condition are true then the next
will execute and the if s[i] != " " and s[i-1] == " "...
part will be skipped for that iteration.
The reason for getting a count of 14 words when you remove the next
relies on knowing what happens when a negative index is used for a string. In this line:
if s[i] != " " and s[i-1] == " "
when i
is 0 this is equivalent to
s[0] != " " and s[-1] == " "
s[-1]
means the last character of the string. This is true for the line "fifth line "
so the result is that the first word of that line is counted twice.
To replace the next
with an else
condition you'd need to arrange an alternative way for the if s[i] != " " and s[i-1] == " "...
not to execute if i == 0 and s[i] != " "
so something like:
if i == 0 and s[i] != " "
wis = 1
elsif s[i] != " " and s[i-1] == " "
wis += 1
end
Upvotes: 3