Beefy Boxes and Bandwidth Generously Provided by pair Networks
Problems? Is your data what you think it is?
 
PerlMonks  

multiple array processing

by f77coder (Beadle)
on Sep 03, 2014 at 01:49 UTC ( [id://1099338]=perlquestion: print w/replies, xml ) Need Help??

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

Hello.

Am looking for some opinions on how to write these operations.

@array1A=qw(a b c d); @array1B=qw(p z e t i u); @array_of_arrays=(@array1A, @array1B, @array2A,@array2B…@arrayNA,@arra +yNB);

sub arrays have different lengths have unique values and don't want to sort them. I want so sort the array_of_arrays based on following

1. sort array based on number of elements in each from smallest to largest

2. is it possible to sort the sub-arrays by name? then size?

3. to do a random sort by name with (1A,2A…) then (1B,2B,…). Example

@array_of_arrays=(@array2A,@array4A,@array1A,…@array1B,@array5B);

the interesting part is the operations on the sub arrays, I do search of each sub array with a scalar value. the following loop has no sorting .

while (<DATA>){ chomp; my @element = split; my $i1=shift @element; my $i2=shift @element; my $i3=shift @element; my $i4=shift @element; shift @element; shift @element; my $i7=shift @element; if(any{ $_ eq $i1} @array1A)) {print 'yes'; }elsif((any{ $_ eq $i1} @array1B)) {print 'no'; }elsif((any{ $_ eq $i2} @array2A)) {print 'yes'; }elsif((any{ $_ eq $i2} @array2B)) {print 'no'; }else{print "WTF";} };

I need the If loop rearranged based on the order of the array_of_arrays Is this possible?

All help is appreciated.

Replies are listed 'Best First'.
Re: multiple array processing
by AnomalousMonk (Archbishop) on Sep 03, 2014 at 03:22 UTC
    1. sort array based on number of elements in each from smallest to largest

    Here's something sort of like what I imagine you might want given the preceding array pseudo-code:

    c:\@Work\Perl>perl -wMstrict -le "use Data::Dump; ;; my @ra_1 = qw(a b c d); my @ra_2 = (1 .. 9); my @ra_3 = qw(p z e t i u); my @ra_4 = qw(foo bar baz); ;; my @AoA = (\@ra_1, \@ra_2, \@ra_3, \@ra_4); dd \@AoA; ;; my @sorted = sort { @$a <=> @$b } @AoA; dd \@sorted; " [ ["a" .. "d"], [1 .. 9], ["p", "z", "e", "t", "i", "u"], ["foo", "bar", "baz"], ] [ ["foo", "bar", "baz"], ["a" .. "d"], ["p", "z", "e", "t", "i", "u"], [1 .. 9], ]
    The statement
        my @AoA = (\@ra_1, \@ra_2, \@ra_3, \@ra_4);
    can also be written
        my @AoA = \(@ra_1, @ra_2, @ra_3, @ra_4);
    for the same effect; the second form is just a short-hand version of the first.

    2. is it possible to sort the sub-arrays by name? then size?

    I don't understand what this means. Do you want to sort by the names of the lexical variables? If so, why? Maybe you really want a more complex structure than an array or array-of-arrays, e.g, a data structure. Please see perldsc.

    3. to do a random sort by name with (1A,2A…) then (1B,2B,…). ...

    Any array can be randomly 'sorted'. See List::Util::shuffle.

    I don't really understand the rest of the code you present in the OP.

    Update: Many incremental changes. Sorry.

      Thanks for the post.

      With regards to 2. each array has different lengths, example from your post

      [ ["a" .. "d"], [1 .. 9], ["p", "z", "e", "t", "i", "u"], ["foo", "bar", "baz"], ]

      I would want that sorted from min to max number of elements

      [ red ["foo", "bar", "baz"], ["a" .. "d"], [1 .. 9], ["p", "z", "e", "t", "i", "u"], ]

      for 3., yes I want to sort the array_of_arrays by the lexical subarray variable names. maybe this needs to be shoved into a string, parsed then ordered??

      a random sort of the arrays might be

      [ [1 .. 9], ["foo", "bar", "baz"], ["p", "z", "e", "t", "i", "u"], ["a" .. "d"], red ]

        f77coder: Further to NetWallah's post, you have to realize that Perl strings are not arrays (e.g., not in the sense that C strings are char arrays). However, they do both have 'length' (number of characters vs. number of elements) and so are comparable. But when you mix strings and array references promiscuously, you must be sure each element is correctly recognized so its 'length' can be correctly derived. (This code assumes only strings and array references are mixed together, and also has a shuffle example.)

        c:\@Work\Perl>perl -wMstrict -le "use List::Util qw(shuffle); use Data::Dump; ;; my @ra_1 = qw(a b c d); my @ra_2 = (1 .. 9); my @ra_3 = qw(p z e t i u); my @ra_4 = qw(foo bar baz); ;; my @AoA = (\@ra_1, 'foozle', \@ra_2, 'red', \@ra_3, \@ra_4); dd \@AoA; ;; my @sorted = sort { (ref $a ? @$a : length $a) <=> (ref $b ? @$b : length $b) } @AoA ; dd \@sorted; ;; my @shuffled = shuffle @sorted; dd \@shuffled; " [ ["a" .. "d"], "foozle", [1 .. 9], "red", ["p", "z", "e", "t", "i", "u"], ["foo", "bar", "baz"], ] [ "red", ["foo", "bar", "baz"], ["a" .. "d"], "foozle", ["p", "z", "e", "t", "i", "u"], [1 .. 9], ] [ [1 .. 9], ["a" .. "d"], "foozle", ["foo", "bar", "baz"], "red", ["p", "z", "e", "t", "i", "u"], ]

        The structure you seem to be heading toward is something like this:
        my @AoA = ([ra_1=> \@ra_1], [ra2=>\@ra_2], [ra3=>\@ra_3], [ra4=>\@ra_ +4]); # Fat comma's used for readability
        This allows you to sort by Size, then name..
        my @AoA_sorted_by_size_Then_Name = sort {@{$a->[1]} <=> @{$b->[1]} || $a->[0] cmp $b->[0]} @AoA;
        *UNTETSED*

                "You're only given one little spark of madness. You mustn't lose it."         - Robin Williams

Re: multiple array processing
by AppleFritter (Vicar) on Sep 03, 2014 at 10:15 UTC
    @array_of_arrays=(@array1A, @array1B, @array2A,@array2B…@arrayNA,@arra +yNB);

    Before I say anything else, let me note that this won't work. Perl flattens lists by default, so e.g. (@array1A, @array1B) is the concatenation of the two arrays, not a two-element list containing two arrays. What you'll want is (\@array1A, \@array1B); alternatively, you can also write \(@array1A, @array1B) (personally I think this is a bit confusing, since it doesn't do what it looks like it'll do, but I'll admit it does look nicer).

    So, that said...

    1. sort array based on number of elements in each from smallest to largest

    Easily done:

    my @a1A = qw/a b c d/; my @a1B = qw/p z e t i u/; my @a2A = qw/F l i n t s t o n e/; my @a2B = qw/f o o/; my @AoA = \(@a1A, @a1B, @a2A, @a2B); my @sorted = sort { @$a <=> @$b } @AoA;

    2. is it possible to sort the sub-arrays by name? then size?

    I'm not sure exactly what sort order you're envisioning there, but variable names are not preserved you take (hard) references to variables, so there is no way to recover e.g. the names "array1A" and "array1B" from @array_of_arrays if you set @array_of_arrays = \(@array1A, @array1B).

    That doesn't mean that what you want is impossible; you'll merely have to use a different data structure, likely something involving hashes. For instance:

    my %HoA = ( "a1A" => \@a1, "a1B" => \@a1B, "a2A" => \@a2A, "a2B" => \@a2B )

    Then pass an appropriate code block to sort to take into account names and array lengths, e.g. this

    my @sorted = sort { substr($a, 0, 2) cmp substr($b, 0, 2) || @{ $HoA{$a} } <=> @{ $HoA{$b} } } keys %HoA; # @sorted is (a1A, a1B, a2B, a2A)

    3. to do a random sort by name with (1A,2A…) then (1B,2B,…). Example

    What does "random" mean? I'm guessing that you want all the "A" arrays first, then all the "B" arrays, without caring about what order they appear in; if so, use the same hash-of-arrays structure as above, and sort like this:

    my @sorted = sort { substr($a, 2, 1) cmp substr($b, 2, 1) } keys %HoA; # sorted is e.g. (a2A, a1A, a1B, a2B)

    If you do care about the order of each block of arrays, add an extra condition:

    my @sorted = sort { substr($a, 2, 1) cmp substr($b, 2, 1) || substr($a, 1, 1) <=> substr($b, 1, 1) } keys %HoA; # sorted is (a1A, a2A, a1B, a2B)

    I need the If loop rearranged based on the order of the array_of_arrays Is this possible?

    Yes.

      I can follow most of this code but what are these variables

       @$a   @$b  "special sorting variables" and  "flying saucer operator" <=>

      Is there any documentation for this more than what is here http://www.perlmeme.org/tutorials/sort_function.html??

        Here in the Monastery, see List Processing, Filtering, and Sorting in Tutorials. See perlvar for info on the  $a $b special variables (used for other things than just sorting), perlop for the spaceship  <=> and its close cousin, the  cmp operator. Also see sort for more info on this built-in function, and the sort pragma for info on controlling it. See also A Fresh Look at Efficient Perl Sorting.

        ... what are these variables

         @$a   @$b

        When sort-ing a list,  $a $b are aliased (see 'alias' in perlglossary) to various pairs of elements in the list to be sorted so that they may be compared and, if necessary, rearranged into sorted order (whatever 'sorted' means in a given context). If a list of array references is being sorted (as in some of the code examples),  $a $b become aliases of these references. If  $scalar is an array reference, then  @$scalar dereferences it. If an array reference is dereferenced in numeric context, then the number of elements of the array is returned.

        If you are sorting a list of array references by the length of each referenced array (i.e., the number of elements in each array) as in
            my @sorted = sort { @$a <=> @$b } \(@ra1, @ra2, @rax, @ray);
        @$a and  @$b in the numeric context imposed by the  <=> (spaceship) numeric comparison operator evaluate to the number of elements in their respective aliased referents.

        Update: Added  @$a <=> @$b explanation.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1099338]
Approved by Old_Gray_Bear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others taking refuge in the Monastery: (5)
As of 2024-04-18 00:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found