I am looking for a more elegant, 'Ruby-ists' way to do the following. Is there any cleaner way to do this?
i=0
array.each do |x|
break if x.empty?
puts x
i+=1
break if i>4
end
I saw that you were calling #empty? on the elements in your array and quitting when you see the first empty element. If you want to preserve that behavior, you could do:
array.first(4).each do |x|
break if x.empty?
puts x
end
A fancier way would be:
array.take_while { |i| !i.empty? }.first(4).each do |i|
puts i
end
I am not sure how many elements you want to print; please note that my examples will print at most 4 elements, whereas your code was printing up to 5.
I'd suggest Array#first as follows:
array.first(4).each do |x|
puts x
end
If you only want to accept the first so many non-nil entries, then filter them out using Array#compact:
array.compact.first(4).each do |x|
puts x
end
If you are concerned about empty values then you could still chain the filters using Array#reject:
array.reject(&:empty?).first(4).each do |x|
puts x
end
Another way:
def printem(a,n)
puts a[0, [a.index(&:empty?) || n, n].min]
end
printem [[], [2],[3],[4],[5],[6]], 4
# <prints nothing>
printem [[1],[2], [],[4],[5],[6]], 4
# 1
# 2
printem [[1],[2],[3],[4],[5],[6]], 4
# 1
# 2
# 3
# 4
printem [[1],[2],[3],[4],[5],[6]], 7
# 1
# 2
# 3
# 4
# 5
# 6
Related
I am trying to print my array with just odd numbers using the block method but i am not too sure how to.
I can print odd numbers using no block but do but do not know how to implement it into the block method { }
#non block method
array = [1,2,3,4,5,6,7,8]
array.each do |i|
if i % 2 == 0
puts "#{i}"
end
end
#output of 2 4 6 8
#block method not sure how
array = [1,2,3,4,5,6,7,8]
array.each {|i| put i if i % 2 == 0 end }
#expected output should be 2 4 6 8
Thank you in advanced !
your block is almost correct you just need to remove the end as it's an inline (or trailing) if method, you also need to use puts and not put
array.each {|i| puts i if i % 2 == 0 }
also, note that ruby has a .even? and .odd? methods you can call on integers
array.each {|i| puts i if i.odd? }
Another option is to select the even? elements and print them afterwards:
array.select(&:even?).each { |i| puts i }
Or alternatively via reject and odd?:
array.reject(&:odd?).each { |i| puts i }
The each call isn't really needed, as you can pass an entire array to puts and it will print each element on a separate line:
puts array.select(&:even?)
# or
puts array.reject(&:odd?)
All of the above will generate the same output:
2
4
6
8
This is my program, Not getting expected output. This need to print Ascending order.Please help me on this
a=[5,7,6,4,1,3,2,8,9,10]
temp=0
i=0
j=0
a.each do |i|
a.each do |j|
if(i>j)
temp=i
i=j
j=temp
end
end
end
puts i
Well, you should not compare i>j, those are index values of an array. You should do a[i]>a[j]. And also swap values using array and not array_index. If it doesn't bring the output post the error log.
#example
a=[3,2,1]
a.each{|x| puts x}
#output:
3
2
1
This means that x represents values inside a, but if you tried to do something like this:
a=[3,2,1]
a.each{|x| x = 5}
array a will not change, to change the values you can do this (using each_index method):
a.each_index {|x| a[x]=5}
# if you printed the array it will contains three fives.
# Now a = [5,5,5]
# x now will be the indexes 0,1,2,...
so my final solution for you problem is:
a.each_index do |i|
a.each_index do |j|
if(a[i]<a[j])
temp=a[i]
a[i]=a[j]
a[j]=temp
end
end
end
print a
Another solution with for loop:
a=[5,7,6,4,1,3,2,8,9,10]
for i in 0..a.length-1 do
for j in i..a.length-1 do
if a[i]>a[j]
a[i],a[j] = a[j],a[i] #swap
end
end
end
print a
Note:
You had a problem with the condition, You have to use less than instead of greater than if you want to print then in Ascending Order, if you used my for way the greater than will be used, it is a matter of how your algorithm and your loop works.
for i in [0..4] do
puts i + 1
end
undefined method `+' for 0..4:Range (NoMethodError)
Why is it not treating each number in the range as a fixnum within the loop?
[0..4] is actually array with one range element, the same as [(0..4)]. You need to change it to (0..4).
Write instead:
for i in 0..4 do
Otherwise you don't have a range, you have an array containing 1 range.
There are different ways to achive a goal:
0.upto(4) { |i|
puts i
}
0.step(4, 1) { |i|
puts i
}
5.times { |i| # 5 for inclusive
puts i
}
for i in 0..4
puts i
end
Everything will output:
# ⇒ 0
# ⇒ 1
# ⇒ 2
# ⇒ 3
# ⇒ 4
Hope it helps.
I'm trying out the following code:
a = [1,2,3,4]
a.each do
puts "Removing #{a.last}"
a.pop
end
but instead of getting all four numbers popped I only get the first 3. Indeed, doing something like puts a.length returns 1 and puts-ing it shows the element "1" is still there.
How do I need to use the method correctly?
(I'm using Ruby 2.0).
I suspect this is happening because you're iterating over the elements of the list while modifying the list.
Try the following:
a = [1,2,3,4]
until a.empty? do
puts "Removing #{a.last}"
a.pop
end
Problem
While you are iterating over a you are changing it.
Explanation of Problem
That means once you have removed an element the each method gets thrown off because suddenly the number of elements a contains is one less. And thus indexing is also thrown off.
If I just execute this:
a = [1,2,3,4]
a.each do
|thing|
puts thing
a.delete(thing)
end
I will get the output [1,3].
That is because the following happens:
Before I remove the 1 from the list that is at index 0, the 2 is at index 1.
After the 1 is removed the 2 is at index 0 instead of 1 so not the 2 is the next element that is iterated over but the 3!
By the way you can define a local block variable like I did with thing to access each element that you iterate over.
Solution
In order to get what you want you need to create a copy and work on that.
a = [1,2,3,4]
b = a.clone
a.each do
|thing|
puts thing
b.delete(thing)
end
Now a remains the same while you iterate over it and you change b instead.
So at the end of this loop a = [1,2,3,4] and b =[].
After you said a = b you will have the desired result.
Of Course you can adapt this for popping elements from the back. Just make sure to work on a copy so you do not change the element while you are iteration over it.
Some other answers tell why your code does not work.
An alternative way to do it would be like this (provided that you do not have nil or false in a):
a = [1,2,3,4]
while e = a.pop
puts "Removing #{e}"
end
a = [1,2,3,4]
a.length.times do
puts "Removing #{a.last}"
a.pop
end
Look at the output,which makes clear why it seems to you each not getting run with all the array elements. As you are pop(ing)Array#pop, so the elements from the last is deleted. When each passes 2 to the block,then original array a is got empty,so each stops the iteration.:
a = [1,2,3,4]
a.each do |i|
puts i
puts "Removing #{a.last}"
p a.pop
p "========"
end
Output:
1
Removing 4
4
"========"
2
Removing 3
3
"========"
So you can use the below:
a = [1,2,3,4]
(0...a.size).each do |i|
p a.pop
end
Output:
4
3
2
1
Try this:
a.count.times do a.pop and puts "Removing #{a.last + 1 rescue 1}" end
Should do the same in a do loop
Let's say I have
some_value = 23
I use the Integer's times method to loop.
Inside the iteration, is there an easy way, without keeping a counter, to see what iteration the loop is currently in?
Yes, just have your block accept an argument:
some_value.times{ |index| puts index }
#=> 0
#=> 1
#=> 2
#=> ...
or
some_value.times do |index|
puts index
end
#=> 0
#=> 1
#=> 2
#=> ...
3.times do |i|
puts i*100
end
In this way, you can replace 3 with any integer you like, and manipulate the index i in your looped calculations.
My example will print the following, since the index starts from 0:
# output
0
100
200