increasing counter whithin loop?

  • Thread starter Patrick Gundlach
  • Start date
P

Patrick Gundlach

Hi,

a very basic question...

I'd like to output the sequence "a b d e", by testing if the current
element is == "b" then skip the next element and continue the loop. The
obvious solution doesn't look rubyish to me, how could I use the first
or second attempt to get the desired solution?

Patrick
--------------------------------------------------
a=%w( a b c d e )

# incorrect, outputs "a b c d e"
0.upto(a.size - 1) do |i|
puts a
if a=="b"
# skip next element
# but i won't get affected
i += 1
end
end

# incorrect, outputs "a b c d e"
for i in 0...a.size
puts a
if a=="b"
# skip next element
# but i won't get affected
i += 1
end
end

# incorrect, outputs nothing... is there a next_next ?
a.each do |elt|
puts elt
if elt=="b"
# skip next element
# ??
end
end

# this one works, but is ugly
i=0
while i < a.size
puts a
if a=="b"
# skip next element
i += 1
end
i += 1
end
 
P

Pavel Sokolov

a=%w( a b c d e )

seen = false

a.each {|elem|

unless seen
#do stuff
puts elem
seen = true if elem == "b"
else
seen = false
end
}

cheers,
Pavel
 
R

Robert Klemme

Patrick said:
Hi,

a very basic question...

I'd like to output the sequence "a b d e", by testing if the current
element is == "b" then skip the next element and continue the loop.
The obvious solution doesn't look rubyish to me, how could I use the
first or second attempt to get the desired solution?

Patrick
--------------------------------------------------
a=%w( a b c d e )
a=%w( a b c d e ) => ["a", "b", "c", "d", "e"]
a.each do |elt| ?> next if elt=="b"
puts elt
end
a
c
d
e
=> ["a", "b", "c", "d", "e"]
Kind regards

robert
 
M

Malte Milatz

Patrick Gundlach:
I'd like to output the sequence "a b d e", by testing if the current
element is == "b" then skip the next element and continue the loop.

I do not know whether I understood correctly what you want, but you could
try this:

array = [ :a, :b, :c, :d, :e ]
array.each_with_index do |x, i|
next if array[i-1] == :b
print x, ' '
end

Malte
 
T

ts

try it, with

array = [ :a, :b, :c, :d, :e , :b]

M> array.each_with_index do |x, i|
M> next if array[i-1] == :b
M> print x, ' '
M> end

:)


Guy Decoux
 
N

Neil Stevens

Patrick said:
Hi,

a very basic question...

I'd like to output the sequence "a b d e", by testing if the current
element is == "b" then skip the next element and continue the loop. The
obvious solution doesn't look rubyish to me, how could I use the first
or second attempt to get the desired solution?

array = [1, :skip, :hidden, 2, :skip, :hidden, 3, :skip]

# Zipped to ensure i is uniquely index()ed
# Also makes sure use array non-destructively
zip = array.zip
for i in zip
if i[0] == :skip
zip.delete_at(zip.index(i) + 1)
else
puts i[0]
end
end

Output:

1
2
3
 
M

Malte Milatz

ts:
try it, with

array = [ :a, :b, :c, :d, :e , :b]

Huh. Right. So it becomes

array.each_with_index do |x, i|
next if array[i-1] == :b unless i == 0
print x, ' '
end

Nasty.

Malte
 
G

Gary Watson

a = ["a", "b", "c", "d", "e"]

temp = nil

p a.select {|x| if temp == "b" then temp = nil; next end; temp = x;true}


outputs

["a", "b", "d", "e"]

Probably could be cleaner.
 
R

Rich

Maybe I'm just being thick, but wouldn't it just be easier (and much
closer to what you are actually trying to do) to say

["a", "b", "c", "d", "e"].each do |x|
puts x unless x =3D=3D "c"
end

I'll admit I'm also new to Ruby but isn't the above the more "rubyish"
way to achieve what you're trying to do?
 
P

Patrick Gundlach

Hello again,


thanks for the answers. I have been very unclear what I wanted, but
Malte, Guy and JEGII seemed to have read my mind.

a=%w( a b b d b e )

a.each_with_index do |x, i|
next if x == "b" and a[i - 1] == "b"
if x=="b" and a[i+1]=="b"
puts "double b"
else
puts x
end
end

(slightly different code example, but closer to what I wanted).


I wonder why I cannot change the variable in

for i in 0...x

end

Or am I missing some magic?

Patrick
 
M

Martin DeMello

Patrick Gundlach said:
Hello again,


thanks for the answers. I have been very unclear what I wanted, but
Malte, Guy and JEGII seemed to have read my mind.

a=%w( a b b d b e )

a.each_with_index do |x, i|
next if x == "b" and a[i - 1] == "b"
if x=="b" and a[i+1]=="b"
puts "double b"
else
puts x
end
end

I'd use Gary Watson's method, and cache the last seen element, rather
than rely upon the index (e.g. if you use a stream rather than an array,
you no longer have access to a[i-i]).

martin
 
T

Trans

Maybe I missed something.

last = nil
%w( a b c d e ).select { |e| r = last != 'b' ; last = e ; r }

T.
 
P

Patrick Gundlach

Maybe I missed something.

You missed to read my mind; my explanation was very unclear. I wanted
to have something like

"if two 'b' are consecutive, output 'double b' and continue with the
element behind the second".

'a' 'b' 'b' 'c' 'b' 'd'

->

'a' 'double b' 'c' 'b' 'd'

This is why I thought

for i in sequence
if sequence=='b' and sequence[i+1]=='b'
output 'double b'
# increase i, so that the second 'b' won't be seen by the for-loop
# but ruby won't let me!?
# i += 1 does nothing
else
output sequence
end
end

would work, but I can't change the i in the for-loop. This is a pity!

Patrick
 
K

Kevin Brown

[...]
If you're really tied to the traditional for loop, you can use a while
loop and do the increment yourself at the end of the loop, but usually
you find a better way to do it in Ruby that doesn't involve going through
the chars one at a time, and that's why we rarely use the for construct.

That is exactly what I am trying to find. I have a list (Array) of
different elements, which I want to render below each other, except
when there are two elements of type 'b', they can be put next to each
other. So I think I need a check like 'if this element is == 'b' and
next element is also == 'b', then render them next to each other. This
rendering has to be known in advance, so I can't use information if
the last element is of type 'b' (with the second occurance of 'b').

Of course, I can write a while loop, but this would be

a) setting some counter to 0
b) accessing the elements via [] (index)
c) checking on counter <=> sequence.length

all which are acceptable, but don't look like the nice ruby builtins
that I am used to. The

sequence.each do |element|
....
end

would be nice, but I understand that there is no
'skip_the_next_element'-method. So the next nicer attempt would be

for counter in 0...element.size
# ...
increase_counter_by_one_to_skip_one_interation
end

But - contradicting my intuition - doesn't seem to work/exist. So I
have to stick to an ugly while loop.... ;-) So my question is: did I
miss something? Is there any reason why we can't manipulate the
counter within the loop?

No, you can manipulate the counter just fine, just that it won't persist for
the next iteration of the count. This is because ruby is providing the i for
you, but not actually checking it to know where it is, or when it's done,
unlike similarly worded constructs in C etc.

How about something like:

irb(main):008:0> "abbcdeef".gsub(/(\w)\1/) { |match|
irb(main):009:1* " double #{match[0, 1]} "
irb(main):010:1> }
=> "a double b cd double e f"
 
P

Patrick Gundlach

Hi Kevin,

[for i in ..... end ]
No, you can manipulate the counter just fine, just that it won't persist for
the next iteration of the count. This is because ruby is providing the i for
you, but not actually checking it to know where it is, or when it's done,
unlike similarly worded constructs in C etc.

That (last part of the sentence) is exactly what confused me. Nobody
else thinks that this persistance would be useful?


Patrick
 
K

Kevin Brown

? How else should I expect a behaviour, if not from other languages?

Perhaps how Ruby defines the construct, since it's not another language?

The general idea here is simply that the Ruby way(R) isn't about skipping
elements when going through one at a time. That's why this construct doesn't
work like you're expecting, because there are more Ruby-ish ways to
accomplish it, but do please come up with an example where this is the best
way to do it, and I'll be more than happy to calm down and stop whining at
you. :)
[...]
Use RegExps to do your string processing then.

Yes, but as soon as my elements aren't strings anymore, I need another
solution.

Ok, so what are your elements? ;-)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,200
Messages
2,571,046
Members
47,646
Latest member
xayaci5906

Latest Threads

Top