Re: 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

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

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, Matthew S. [email protected] wrote:

On Jul 3, 2006, at 14:59, Dark A. wrote:

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 Jul 3, 2006, at 14:59, Dark A. 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, 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 16:07, Dark A. wrote:

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 7/3/06, Matthew S. [email protected] wrote:

end
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

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