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.
Re: multiple array processing
by AnomalousMonk (Archbishop) on Sep 03, 2014 at 03:22 UTC
|
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.
| [reply] [d/l] [select] |
|
[
["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
]
| [reply] [d/l] [select] |
|
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"],
]
| [reply] [d/l] [select] |
|
|
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
| [reply] [d/l] [select] |
|
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.
| [reply] [d/l] [select] |
|
| [reply] [d/l] |
|
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.
| [reply] [d/l] [select] |
|
|