solocazzimiei has asked for the wisdom of the Perl Monks concerning the following question:

Hi, I implemented this code to separate a bunch of files into different categories(%dig and so on). When thought to speed up a little the iteration eliminating form both @img and @vid the items already processed by the last two grep statements, I noted instead that after few iterations the $img variable were returning, at the beginning of the loop, the correct file name but anticipated with the following symbols "?^:". I thought that the loop would affected in some way by this "dynamical" sizing of its array ... what you think about this results ? ... or maybe is my dev ambient "Perl Builder 2.0" for win. ..can you recommend me a different one, more optimized for x64 ? free of charge for instance ? Thanks Simon

....... $footprint_im = 'jpg gif png tiff tif'; $footprint_iv = '^vid.+ 3gp mp4 avi'; $footprint_lnk = 'lnk'; $footprint_im .= ' '.uc $footprint_im; $footprint_im =~ s/ /\$\|/g; $footprint_iv .= ' '.uc $footprint_iv; $footprint_iv =~ s/ /\$\|/g; $footprint_lnk .= ' '.uc $footprint_lnk; $footprint_lnk =~ s/ /\$\|/g; for($i = 1 ; $i <= @ff ;$i++){ next if grep{/$i/}@input; clean($ff[$i-1]); } sub clean{ my $dir = shift; $dir =~ s/\\/\\\\/g; $dir .='\\\\'; opendir F, $dir; @imgg = readdir F; @lnk = grep{/$footprint_lnk/} @imgg; @img = grep{/$footprint_im/} @imgg; # @img = grep{/jpg$|JPG$|gif$|GIF$|png$|tiff$|TIFF$/} @imgg; @vid = grep{/$footprint_iv/} @imgg; closedir F; undef @imgg foreach $img(@img,@vid){ # $img = (@img,@vid)[$i]; # $rr = $img; # $rr =~ s/\(\?\^\:(.+)\)/\1/; # $rr =$1; open my $fh, '<', $dir.$img; my $md5 = Digest::MD5->new->addfile($fh)->hexdigest; close $fh; if ((!$dig{$md5}) and (grep {/$img/} @img)){ $dig{$md5} = $dir.$img ; $dig = values %dig; print R "$md5\t$dir.$img\n"; }elsif ((!$dig_v{$md5}) and (grep {/$img/} @vid)){ $dig_v{$md5} = $dir.$img ; $dig_v = values %dig_v; print R "$md5\t$dir$img\n"; }else{ $del{$md5} = $dir.$img ; } # splice(@img,$i,1) if $rr =~ /$footprint_im/;; @img = grep {!/$rr/} @img; @vid = grep {!/$rr/} @vid; } ...... }

Replies are listed 'Best First'.
Re: Strange result on array
by choroba (Cardinal) on Mar 30, 2021 at 18:33 UTC
    See perlsyn:

    > If any part of LIST is an array, foreach will get very confused if you add or remove elements within the loop body, for example with splice. So don't do that.

    You don't use splice, but instead you change the arrays the loop iterates over:

    @img = grep {!/$rr/} @img; @vid = grep {!/$rr/} @vid;

    So don't do that.

    map{substr$_->[0],$_->[1]||0,1}[\*||{},3],[[]],[ref qr-1,-,-1],[{}],[sub{}^*ARGV,3]

      So both splice and grep have almost the same crazy effect on foreach statement.. thus we will not doit ! many tanks for the confirmation

Re: Strange result on array
by Marshall (Canon) on Mar 31, 2021 at 03:32 UTC
    I am really having trouble making any sense of your code.

    I started by re-organizing your first statements with spacing
    and some print statements:

    use strict; use warnings; my $footprint_im = 'jpg gif png tiff tif'; $footprint_im .= ' '.uc $footprint_im; $footprint_im =~ s/ /\$\|/g; print "footprint_im = $footprint_im\n\n"; # footprint_im = jpg$|gif$|png$|tiff$|tif$|JPG$|GIF$|PNG$|TIFF$|TIF my $footprint_iv = '^vid.+ 3gp mp4 avi'; $footprint_iv .= ' '.uc $footprint_iv; $footprint_iv =~ s/ /\$\|/g; print "footprint_iv = $footprint_iv\n\n"; # footprint_iv = ^vid.+$|3gp$|mp4$|avi$|^VID.+$|3GP$|MP4$|AVI my $footprint_lnk = 'lnk'; $footprint_lnk .= ' '.uc $footprint_lnk; $footprint_lnk =~ s/ /\$\|/g; print "footprint_lnk = $footprint_lnk\n\n"; # footprint_lnk = lnk$|LNK
    I am very confused about where @input comes from?

    A statement like this: for($i = 1 ; $i <= @ff ;$i++){} means to iterate to the number of elements in the ff array. WHAT?

    Perhaps start by explaining what you are trying to do. Then get some code to compile with use warnings; use strict;

    Update: Perhaps:

    my @image_files = grep{/\.jpg$|\.gif$|\.tiff$|\.tif$/i}readdir $target +_dir; my @video_files = grep{/^VID.+|\.3gp$|\.mp4$|\.avi$/i}readdir $target_ +dir;
    Oh, I am a bit dubious about the "begins with VID" idea.