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

hello monks

Ok, I fixed most of my problems

but I found another instance where my @sorted= shift@_ didn't work. it worked with @_ only

my @sorted= @_; #using shift didn't work, why? format?

trying to read about it to find solution/explanation but no luck yet

Anyhow, still looking to create an algorithms to find the element that appears the most and return it

not too much luck so far but working on this still

Monks , I am updating the previous post coz yesterday I was to frustrated not finding solutions to my issues

still trying to find how to properly use/pass a var=value from inside one sub into another sub

this is the code I fix

use strict; use warnings; use autodie; use Data::Dump qw(dump); open my $in, '<', 'numbers.txt' or die $!; my @data =split/\s+/,<$in>; close $in; my ($mean,$ref,@new_sort)= sort_num(@data); my $length=$$ref; #passing by ref example #print "sorted : @new_sort\n"; print "mean : $mean\n"; print "length : $length\n"; my ($middle,$median)=median_num(@new_sort); print "this is median : $median\n"; print "this will be middle num position : $middle\n"; my ($size,$hash_ref)=mode_num( {NUMBERS=>\@new_sort} ); # my $true_size=$$size; print "this is length :$true_size\n"; foreach my $k (keys %$hash_ref){ for (0..$length){ print " $hash_ref->{$k}[$_]"; #%hash->NUMBER=> i_number #there are + undef but dump doesn't show these } } # my sub practice with ref and hash_ref sub sort_num{ our @sorted=sort {$a <=> $b}@_; our $length = scalar (@sorted); our $add_div_elem =(eval join '+',@sorted)/$length; median_num(\@sorted); return $add_div_elem,\$length,@sorted; } sub median_num{ my @sorted= @_; #using shift didn't work, why? format? my $middle_one = eval ((scalar @sorted)+ 1)/2; my $median=$sorted[$middle_one]; return ( $middle_one, $median)# } #passing by references sub mode_num{ my %opt = %{shift @_ } ; #creating hash my $size=keys %opt->{NUMBERS}; #getting size of hash #my %count=(); #for (0..$size){ #have to defined the hash coz perl will see 0 if undef # foreach my $key ( keys %opt->{$key}){ # my $value= $opt->{$key}[$_]; # if (not exists $count{$value}){ # $count{$value}=[]; # } # push $count{$value},$key; # } #} return \$size,\%opt; }

Replies are listed 'Best First'.
Re: unxpected sort warnings while using sort
by NetWallah (Canon) on Jul 22, 2015 at 23:06 UTC
    Take out:
    local $/; # slurp mode
    since you want individual numbers in separate array elements.

    It is also a good idea to

    chomp @data;
    after reading it in.

    <=> is the right operator for sorting numerics.

    instead of "(my @num= shift)", use

    my @sorted=sort {$a<=>$b} @_;

            "Despite my privileged upbringing, I'm actually quite well-balanced. I have a chip on both shoulders."         - John Nash

      made changes but no change in output

      commented out slurp

      made reable code by using @_ as used per subs

      no sort and no change in message

      open my $in, '<', 'numbers.txt' or die $!; # local $/; # slurp mode my @data = <$in>; chomp @data; close $in; sort_num(@data); my @new_sort=sort_num(); print "this is new sorted data ;",@new_sort; sub sort_num{ my @sorted=sort {$a <=> $b}@_; return @sorted; }
      Argument "2 3 3 3 5 7 8 12 32 44 55 12 3 23 43 33 1 4 25 43 42 1" isn' +t numeric in sort at C:\Users\Alberto\Documents\NetBeansProjects\Perl +Project\Perl Essentials\subroutines\ave_mode_median_range sub.pl line + 24. this is new sorted data ;

        What is your data? The warning message
            Argument "2 3 3 3 5 7 8 12 32 44 55 12 3 23 43 33 1 4 25 43 42 1" isn't numeric in sort at ...
        shows that Perl still thinks it's a single string with a bunch of digits and spaces in it. sort will never sort this numerically — or any other way, since it's just a single-element list and so is already "sorted"!


        Give a man a fish:  <%-(-(-(-<

        As AnomalousMonk has pointed out, the way your data is formatted is important.

        The way most programmers would expect to see your data is like this:

        2 3 3 3 5 7 8 12 ...
        If, instead, it looks like this:
        2 3 3 3 5 7 8 12 ...
        then you have a problem .. or rather, it needs to be handled differently in your code.

        For the second case, you need:

        my @data = split /\s+/,<$in>;

        In addition, the way the "sort_num" is called has some issues in your code.

        This is how it should be called:

        my @new_sort = sort_num (@data);
        And call it only ONCE.

                "Despite my privileged upbringing, I'm actually quite well-balanced. I have a chip on both shoulders."         - John Nash

        Strongly suggest using Data::Dumper to see what your data is and looks like.

Re: unxpected sort warnings while using sort
by AnomalousMonk (Archbishop) on Jul 23, 2015 at 03:53 UTC

    If your data exists in a file as a single line of unsigned integers, then you need to extract these integers (digit groups) from the line to a list or array, perhaps after chomp-ing the line (although that may not be necessary if the line is just digits and whitespace with a newline at the end), and then numerically sort the list/array using the  <=> comparator.

    c:\@Work\Perl\monks>perl -wMstrict -MData::Dump -le "my $line = '2 3 3 3 5 7 8 12 32 44 55 12 3 23 43 33 1 4 25 43 42 1'; dd $line; ;; my @raw_numbers = $line =~ m{ \d+ }xmsg; ;; my @sorted_numbers = sort { $a <=> $b } @raw_numbers; dd \@sorted_numbers; " "2 3 3 3 5 7 8 12 32 44 55 12 3 23 43 33 1 4 25 43 42 1" [1, 1, 2, 3, 3, 3, 3, 4, 5, 7, 8, 12, 12, 23, 25, 32, 33, 42, 43, 43, +44, 55]
    But again, what is your input data really like? You can see this with something like Data::Dumper::Dumper(), which should be available in any Perl installation, or Data::Dump::dd(), which I like, or even with individual print statements.


    Give a man a fish:  <%-(-(-(-<

      I think you got the issue corrected for me...it is the input data that was constructed (by me and Unknowingly thought it'd be used as numbers and not string) as a string.

      2 3 3 3 5 7 8 12 32 44 55 12 3 23 43 33 1 4 25 43 42 1

        To be fair, Perl will usually just "do the right thing" for you with numbers inside strings.

        But it can only read your mind so far. See:

        my $var1 = "12345"; my $res1 = $var1 + 1; print "Result 1: [$res1]\n";

        Results in:

        Result 1: [12346]

        However:

        my $var2 = "1 2 3 4 5"; my $res2 = $var2 + 1; print "Result 2: [$res2]\n";

        Results in:

        Result 2: [2]

        You see how Perl took the first number in the line and added 1 to it? But the rest of the line has been ignored, and thrown away.

        If you want the rest of the numbers used, as noted throughout this thread, you have two choices:

        1. Process them in a way that uses them, such as the use of split, or;
        2. Put them on separate lines so file reading gets them separately.

Re: unxpected sort warnings while using sort
by Laurent_R (Canon) on Jul 23, 2015 at 10:16 UTC
    If the pieces of advice given to you so far are not sufficient to solve your issue, then you should really post a sample of your input file, so that we can know how to handle its contents.
Re: unxpected sort warnings while using sort
by AnomalousMonk (Archbishop) on Jul 27, 2015 at 03:17 UTC
    ... I am updating the previous post ...

    No, you deleted the previous post and replaced it with something quite different. In doing so, you rendered all previous replies incoherent, meaningless. Any future Seeker of Perl Wisdom who ventures down this path will find the signposts defaced and destroyed, the trail erased. Please don't do this again. A -- from me.

    Update: Please note that it's perfectly acceptable to actually update, i.e., modify or expand, a post as long as the original material, to which replies may have been made, is preserved and a brief note is added saying what modifications or additions have been made.


    Give a man a fish:  <%-(-(-(-<

      I am sorry I modified it

      I thought the "update" button really did an update rather than delete but I guess not.

      will learn from this and not delete any post in future

      bummer, man, I wanna this to be used for someone else , if they had the same questions I do as I learn Perl.

      again, I DO apologize for the error

      I wish I could double ++this post; once for the oft-needed chastisement against modifying nodes wholesale, and an additional one for the recursive reference when you edited a post about editing posts, thus showing one way to do it.

Re: unxpected sort warnings while using sort
by marinersk (Priest) on Jul 27, 2015 at 02:32 UTC

    You really need to start learning to use the debugging tools you've chosen -- in thise case, Data::Dump.

    I wrote my own data dumper so I apologize for using a nonstandard module here to demonstrate, but it gets the point across quite nicely. I made the following changes:

    sub median_num{ my @sorted= @_; #using shift didn't work, why? format? &debug::debugdumplist("median_num(): \@sorted", \@sorted);

    Notice in the results how median_num()receives two different types of structures:

    D:\PerlMonks>shift3.pl Using a hash as a reference is deprecated at D:\PerlMonks\shift3.pl li +ne 54. median_num(): @sorted (S:/Steve/Perl/debug.pm:887): [ARRAY(0x2ae0c28)] [1] [1] [2] [3] [3] [3] [3] [4] [5] [7] [8] [12] [12] [23] [25] [32] [33] [42] [43] [43] [44] [55] mean : 18.3636363636364 length : 22 median_num(): @sorted (S:/Steve/Perl/debug.pm:887): [1] [1] [2] [3] [3] [3] [3] [4] [5] [7] [8] [12] [12] [23] [25] [32] [33] [42] [43] [43] [44] [55] this is median : 12 this will be middle num position : 11.5 this is length :22 Use of uninitialized value in concatenation (.) or string at D:\PerlMo +nks\shift3.pl line 29. 1 1 2 3 3 3 3 4 5 7 8 12 12 23 25 32 33 42 43 43 44 55 D:\PerlMonks>

    Look closely at the first one; the @sortedarray contains another ARRAY; and that array then has scalar values in it. This is an array of arrays.

    Look at the second one; no embedded ARRAY; @sortedsimply contains scalar values.

    So I looked at the lines in your code which call median_num(), and lo and behold, you are not using the subroutine consistently:

    my ($middle,$median)=median_num(@new_sort); median_num(\@sorted);

    The first line calls median_num()with an array as its parameter list.

    The second one calls it with a REFERENCE to an array. In Cterms, you've passed it by reference instead of by value

    Betting this inconsistency has something to do with why shiftdidn't work.

    Also, you might want to clean up your errors and warnings, but you probably knew that.

      the use of value and by reference was an exercise for me to learn how to do it.

      Monks

      I need help with my sub routine

      I cannot find a way to create a counter and test for the most duplicated number in the hash

      have tried on my own but not successful. Please help so I can see how to do this properly

      problem section below
      sub mode_num{ my %count=(); %opt = %{shift @_ } ; #creating hash #dump \%opt; #check data coming in.. #need to get integrate count as I format data into hash(next task + to make it reable) for (sort{$a <=> $b} %opt{NUMBERS}){ #dump \$opt{NUMBERS}++; $opt{NUMBERS}++; } our @keys= sort{$opt{NUMBERS}->{$b}<=>$opt{NUMBERS}->{$a}} key +s %opt{NUMBERS}; return $opt{NUMBERS}[0]; #some $keys[0] here but don't know proper +syntax...or correct method }
      DATA
      2 3 3 3 5 7 8 12 32 44 55 12 3 23 43 33 1 4 25 43 42 1 4 5 3 3 3
      Complete code
      # will find ave, media, range,mode and mean use strict; use warnings; use autodie; use Data::Dump qw(dump); open my $in, '<', 'numbers.txt' or die $!; # local $/; # slurp mode my @data =split/\s+/,<$in>; close $in; my ($mean,$ref,@new_sort)= sort_num(@data); my $length=$$ref; #passing by ref example print "Input Data set : @new_sort\n"; print "Mean : $mean\n"; print "Lenght : $length\n"; my ($middle,$median)=median_num(@data); print "Median : $median\n"; print "Position of median number : $middle\n"; #using reference to build hash and find most duplicated num my ($hash_ref)=mode_num( {NUMBERS=>\@new_sort} ); #foreach my $k (keys %$hash_ref){ # for (0..$length){ # print " $hash_ref->{$k}[$_]"; #%hash->NUMBER=> i_number # } # } my ($mode_num)=alt_mode_num(@data); print "Mode : $mode_num\n"; # my sub practice with ref and hash_ref sub sort_num{ our @sorted=sort {$a <=> $b}@_; our $length = scalar (@sorted); our $add_div_elem =(eval join '+',@sorted)/$length; median_num(\@sorted); return $add_div_elem,\$length,@sorted; } sub median_num{ my @sorted= @_; #using shift didn't work, why? format? my $middle_one = eval ((scalar @sorted)+ 1)/2; my $median=$sorted[$middle_one]; return ( $middle_one, $median) } #passing by references sub mode_num{ my %count=(); %opt = %{shift @_ } ; #creating hash #dump \%opt; #check data coming in.. #need to get integrate count as I format data into hash(next task + to make it reable) for (sort{$a <=> $b} %opt{NUMBERS}){ #dump \$opt{NUMBERS}++; $opt{NUMBERS}++; } our @keys= sort{$opt{NUMBERS}->{$b}<=>$opt{NUMBERS}->{$a}} key +s %opt{NUMBERS}; return } #alternate to get most repeated num. need to know while using NUMBE +RS ref sub alt_mode_num{ my %count=(); for (sort{$a <=> $b} @_){ $count{$_}++; } my @key= sort{$count{$b}<=>$count{$a}} keys %count; return $key[0]; }
        #!/usr/bin/perl use warnings; use strict; sub most_duplicated { my @numbers = @_; my %count; ++$count{$_} for @numbers; my @most_duplicated; my $max_count = 0; for my $n (keys %count) { if ($count{$n} > $max_count) { @most_duplicated = ($n); $max_count = $count{$n} } elsif ($count{$n} == $max_count) { push @most_duplicated, $n; } } return ($max_count, \@most_duplicated) } my @data = qw( 2 3 3 3 5 7 8 12 32 44 55 12 3 23 43 33 1 4 25 43 42 1 4 5 3 + 3 3 ); my ($count, $most_duplicated) = most_duplicated(@data); print "@$most_duplicated occurred $count times.\n";

        It's also possible to avoid two loops and do all the work in one loop, but I think this way is more understandable.

        لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ