If problem in loop causing weirdness

You can use the break command to stop iterating through a block, eg.
(simplifying your commands a bit):

file_names=['a.txt','b.txt','c.txt']
file_names.each do |x|
if x=='b.txt'
puts 'we already have ' + x + ' in that array '
break
end
end

Best regards,

Axel

Break doesn't seem to be the solution. To jump ahead to the
behaviour, when asked if I want to overwrite, if answer is no, then
everything behaves properly. If yes, which is covered in the else
portion following 'get', it asks me 4x (there are 5 files in the
directory I'm using. I've tried 'break' in various places (where it
might have made sense) but didn't seem to correct the behaviour.

Stuart

···

On 7/3/06, Nuralanur@aol.com <Nuralanur@aol.com> wrote:

You can use the break command to stop iterating through a block, eg.
(simplifying your commands a bit):

file_names=['a.txt','b.txt','c.txt']
file_names.each do |x|
if x=='b.txt'
puts 'we already have ' + x + ' in that array '
break
end

Best regards,

Axel

I suspect that the problem is with the deletion from an array within a loop
of that array.

Solution: construct a different array such that => if ow != 'no' then
new_array.push(x); end;

consider the following test.

irb(main):013:0> x = [1,2,3,4]
=> [1, 2, 3, 4]
irb(main):014:0> x.each { |ii|
irb(main):015:1* print "ii = #{ii}\n"
irb(main):016:1> print "x = #{x}\n"
irb(main):017:1> x.delete(ii)
irb(main):018:1> print "x now = #{x}\n"
irb(main):019:1> }
ii = 1
x = 1234
x now = 234
ii = 3
x = 234
x now = 24
=> [2, 4]

While this does not demonstrate your issue persay, it does however
illustrate a bug. ii never equals the value of the original second index,
because the array's iterator does not go back a step on deletion.

Hope this helps.

-trav

···

--
p [151,40,154,157,166,145,40,162,165,142,171].collect { |ii| eval
'"\\'+ii.to_s+'"' }.join

I 'suspected' this as I had a similar issue (different behaviour) in
my last previous thread.

What I had to do to correct things is if 'yes', push into the new
array AND still delete from former array, and if 'no', just delete
from former/existing array. Weird I think(?) especially in regards to
the 'no', but without the delete, it continues to loop on the gets.
Reposting my code just to show what I've changed. Things are working
correctly not (until at least I add the next function :)). Thank you
for the help!

destdir = Dir['C:/testfilesmoved/*.*']
         newmove =
         destdir.each do |name|
           pics2bmoved.each do |x|

              if File.exist?(name) && File.compare(x, name) == true
              puts x + ' already exists'
              puts 'Do you want to overwrite? "yes" or "no"?'
              ow = gets.chomp.downcase

              if ow == 'yes' <======== corrected
              newmove.push(x)
              pics2bmoved.delete(x)
                else <============= corrected.
                  pics2bmoved.delete(x)
                  puts 'okay, file will not be overwritten'

              end # for if file.exist?
          end # ow
      end # end for pics2bmoved loop
  end # end for destdir loop

  puts
    if newmove.empty?
      puts 'There are no files to be moved'
       else
            puts 'The following files will be moved'
            puts newmove
    end # for pic2bmoved list

···

--------------------------------------------------------------------------------------------------------------
On 7/3/06, Travis Michel <meshac.ruby@gmail.com> wrote:

I suspect that the problem is with the deletion from an array within a loop
of that array.

Solution: construct a different array such that => if ow != 'no' then
new_array.push(x); end;

consider the following test.

irb(main):013:0> x = [1,2,3,4]
=> [1, 2, 3, 4]
irb(main):014:0> x.each { |ii|
irb(main):015:1* print "ii = #{ii}\n"
irb(main):016:1> print "x = #{x}\n"
irb(main):017:1> x.delete(ii)
irb(main):018:1> print "x now = #{x}\n"
irb(main):019:1> }
ii = 1
x = 1234
x now = 234
ii = 3
x = 234
x now = 24
=> [2, 4]

While this does not demonstrate your issue persay, it does however
illustrate a bug. ii never equals the value of the original second index,
because the array's iterator does not go back a step on deletion.

Hope this helps.

-trav
--
p [151,40,154,157,166,145,40,162,165,142,171].collect { |ii| eval
'"\\'+ii.to_s+'"' }.join

Not to be negative, but I don't think things are actually working, at least not the way you think they should be. It seems to me that there's no reason you should have to delete entries from the pics2bmoved array in this code, unless pics2bmoved has incorrect data in it to begin with. For example, the following initial conditions give you similar behaviour to what you describe, and would be 'fixed' using delete, since that deletes all of the duplicate entries, but the *real* bug would be in the code which creates pics2bmoved:

destdir = ["/foo/a.txt", "/foo/b.txt"]
pics2bmoved = ["/bar/a.txt", "/bar/a.txt", "/bar/a.txt", "/bar/b.txt", "/bar/b.txt", "/bar/b.txt"]

So, basically, I have a *very* strong hunch that the bug you're seeing here actually exists somewhere else and that you're curing the symptom and not the disease. You should be able to confirm this by checking the state of the pics2bmoved variable before starting the loop, possibly as follows:

destdir = Dir['C:/testfilesmoved/*.*']
newmove =

puts pics2bmoved # ADDED THIS

destdir.each do |name|
   pics2bmoved.each do |x|
[...]
   end
end

This is part of a two-part general strategy that will really help you when you're learning to program. The first part is to work out what you *think* should be happening all the way through the code. The second part is to confirm that it's *actually* happening the way you think. Using 'puts' as above is the dead-simple way to do it, which lets you manually check that what's going on matches what you expect. There are various ways to automate this sort of checking, but doing it manually is probably best at first.

Following on from previous questions of yours, I'll also point out that you've got the ends of the if statements mislabelled again. Remember, the first one started is the *last* one ended. You've got the loops right, though.

matthew smillie.

···

On Jul 3, 2006, at 14:59, Dark Ambient wrote:

I 'suspected' this as I had a similar issue (different behaviour) in
my last previous thread.

What I had to do to correct things is if 'yes', push into the new
array AND still delete from former array, and if 'no', just delete
from former/existing array. Weird I think(?) especially in regards to
the 'no', but without the delete, it continues to loop on the gets.
Reposting my code just to show what I've changed. Things are working
correctly not (until at least I add the next function :)). Thank you
for the help!

Not to be negative

Your not being negative, I'd rather not program then learn to program
badly (fixing symptoms versus actual bug). Though I know there is
plenty of commercial software out there that does....(well that's for
another discussion)

puts pics2bmoved # ADDED THIS

After inserting this line "I" got thrown for a loop :slight_smile:
First , there are two sections to the program (so far). The first
section loops through the directory asking the users if they want to
move a file. If affirmative, that file gets pushed into the new array
(empty till then) via push. The second section (after the pics2bmoved
is created) is suppose to go through and see if any files will be
overwritten, giving the user the choice to say yes or decline to
overwrite. So, I think one problem is the destdir is continuing to
loop even after pics2bmoved is exhauster. Or something like that :).
Perhaps my next step would be to somehow combine both sections into one.

Following on from previous questions of yours, I'll also point out
that you've got the ends of the if statements mislabelled again.
Remember, the first one started is the *last* one ended. You've got
the loops right, though.

Thought I corrected that in my own reply to my original post. Good
news on the loops though. Is that considered progress
;)....nevermind.

matthew smillie.

Stuart

···

On 7/3/06, Matthew Smillie <M.B.Smillie@sms.ed.ac.uk> wrote:

On Jul 3, 2006, at 14:59, Dark Ambient wrote:

puts pics2bmoved # ADDED THIS

After inserting this line "I" got thrown for a loop :slight_smile:
First , there are two sections to the program (so far). The first
section loops through the directory asking the users if they want to
move a file. If affirmative, that file gets pushed into the new array
(empty till then) via push. The second section (after the pics2bmoved
is created) is suppose to go through and see if any files will be
overwritten, giving the user the choice to say yes or decline to
overwrite.

That sounds like a good description of what you want. Now you need to make predictions of exactly what should happen, so you can be sure everything is working. For example, if you start with 'a', 'b', 'c', 'd', then you want to say 'y,n,y,n' to the 'move?' question, then you should end up with 'a', 'c' at the end of the first section. That's something you can easily verify.

So, I think one problem is the destdir is continuing to
loop even after pics2bmoved is exhauster. Or something like that :).
Perhaps my next step would be to somehow combine both sections into one.

Hmm. This strikes me as a possible misunderstanding of how nested loops work. The inner loop (pics2bmoved.each in this case) is executed once for every element in the outer loop (destdir.each). In a simpler example:

a = ['a', 'b', 'c']
b = [1, 2, 3]
a.each do |letter|
   b.each do |number|
     puts "#{letter}, #{number}"
   end
end

prints the following:
a, 1
a, 2
a, 3
b, 1
b, 2
b, 3
c, 1
c, 2
c, 3

In other words, when you finish the inner loop, it does the next iteration of the outer loop, which restarts the inner loop again (and again...).

Note that if you change the 'puts' to a push onto some array, you could end up with multiple copies of whatever you're pushing:

a = ['a', 'b', 'c']
b = [1, 2, 3]
c =
a.each do |letter|
   b.each do |number|
     c.push(letter)
   end
end
c => ['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c']

Which seems similar to what I guessed your problem might be. Are you creating pics2bmoved in a similar sort of nested loop?

Best of luck,
matthew smillie.

···

On Jul 3, 2006, at 16:07, Dark Ambient wrote:

On 7/3/06, Matthew Smillie <M.B.Smillie@sms.ed.ac.uk> wrote:

Hmm. This strikes me as a possible misunderstanding of how nested
loops work. The inner loop (pics2bmoved.each in this case) is
executed once for every element in the outer loop (destdir.each). In
a simpler example:

a = ['a', 'b', 'c']
b = [1, 2, 3]
a.each do |letter|
   b.each do |number|
     puts "#{letter}, #{number}"
   end
end

prints the following:
a, 1
a, 2
a, 3
b, 1
b, 2
b, 3
c, 1
c, 2
c, 3

Excellent illustration, very helpful , though the results are still forthcoming.

Which seems similar to what I guessed your problem might be. Are you
creating pics2bmoved in a similar sort of nested loop?

pics2bmoved was created using just .push (which was the first section)
However in section 2, it was the inner loop to the destination
directory / or outer array.
This would explain the repeating for the same element. I've gone
ahead and am attempting to condense the two sections into one. I'm
still faced with the same loop issues though for now.

Best of luck,
matthew smillie.

Stuart

···

On 7/3/06, Matthew Smillie <M.B.Smillie@sms.ed.ac.uk> wrote:

Condensed version:

require 'ftools'

Dir.chdir 'C:/testfilesmoved'

require 'ftools'

pic_names = Dir['C:/testfilesorig/*.*']
destdir = Dir['C:/testfilesmoved/*.*']

pics2bmoved =
pic_names.each do |name|

            puts 'Do you wish to move ' + name + 'file?,"yes" or "no" ?'
               decision = gets.chomp.downcase

                     if decision == 'yes'
                          destdir.each do |x|
                             if File.compare(name, x) == false
                                pics2bmoved.push(name)
                                # problem here, first with loop same as b4, so
                                # i removed the files from destdir, so
File.compare wouldn't hit true
                                # yet, the pics2bmoved.push doesn't
seem to work.

                                else
                                    puts 'The file already exists in
destination, overwrite? "yes" or "no" '
                                        ow = gets.chomp.downcase
                                 if ow == 'yes'
                                     pics2bmoved.push(name)
                                     else
                                        puts 'This ' + name + ' will
not be moved'

                                 end # for ow==yes
                           end # for File.compare
                        end # for destdir loop
                    end # for decision == yes
       end # for pic_names loop

           if pics2bmoved.empty?
               puts
               puts 'No files will be moved'
                     else
                     puts pics2bmoved
          end

···

On 7/3/06, Dark Ambient <sambient@gmail.com> wrote:

On 7/3/06, Matthew Smillie <M.B.Smillie@sms.ed.ac.uk> wrote:

> Hmm. This strikes me as a possible misunderstanding of how nested
> loops work. The inner loop (pics2bmoved.each in this case) is
> executed once for every element in the outer loop (destdir.each). In
> a simpler example:
>
> a = ['a', 'b', 'c']
> b = [1, 2, 3]
> a.each do |letter|
> b.each do |number|
> puts "#{letter}, #{number}"
> end
> end
>
> prints the following:
> a, 1
> a, 2
> a, 3
> b, 1
> b, 2
> b, 3
> c, 1
> c, 2
> c, 3

Excellent illustration, very helpful , though the results are still forthcoming.

> Which seems similar to what I guessed your problem might be. Are you
> creating pics2bmoved in a similar sort of nested loop?

pics2bmoved was created using just .push (which was the first section)
However in section 2, it was the inner loop to the destination
directory / or outer array.
This would explain the repeating for the same element. I've gone
ahead and am attempting to condense the two sections into one. I'm
still faced with the same loop issues though for now.
> Best of luck,
> matthew smillie.

Stuart

Just wanted to finish the thread off here by saying I finally have
working code, accomplishing my task of utilizing File.exists? and
eliminating my loop issues. For the sake of my own
self-aggrandizement I'll post the code (open to criticism or comment)

Dir.chdir 'C:/testfilesmoved'

require 'ftools'

pic_names = Dir['C:/testfilesorig/*.*']
destdir = Dir['C:/testfilesmoved/*.*']

pics2bmoved = []
pic_names.each do |name|

      puts 'Do you wish to move ' + name + 'file?,"yes" or "no" ?'
      decision = gets.chomp.downcase

                  if decision == 'yes'
                    if destdir.empty?
                      pics2bmoved.push(name)
                      else
                    if File.exists?(destdir[name.to_i]) == false
                        pics2bmoved.push(name)

                        else
                        puts name + ' already exists in destination,
overwrite? "yes" or "no" '
                        ow = gets.chomp.downcase

                          if ow == 'yes'
                           pics2bmoved.push(name)
                            else
                            puts 'This ' + name + ' will not be moved'

                    end # ow == yes
                  end # File.exists?
                end # destdir.empty?
             end # decision == yes
           end # for pic_names loop

                   if pics2bmoved.empty?
                   puts
                   puts 'No files will be moved'
                   else
                     puts
                     puts 'These files will be moved'
                     puts pics2bmoved

                  end