Is there a way to modify sort that any string starts with # is ignored i.e. keep its index?
For example:
my @stooges = qw(
Larry
Curly
Moe
Iggy
);
my @sorted_stooges = sort @stooges;
@sorted_stooges
should give:
Curly
Iggy
Larry
Moe
Now, if i add # to Curly
my @stooges = qw(
Larry
#Curly
Moe
Iggy
);
my @sorted_stooges = sort @stooges;
i would like @sorted_stooges to be:
Iggy
#Curly
Larry
Moe
In-place solutions:
my @indexes_to_sort = grep { $array[$_] !~ /^#/ } 0..$#array;
my @sorted_indexes = sort { $array[$a] cmp $array[$b] } @indexes_to_sort;
@array[@indexes_to_sort] = @array[@sorted_indexes];
or
my @indexes_to_sort = grep { $array[$_] !~ /^#/ } 0..$#array;
@array[@indexes_to_sort] = sort @array[@indexes_to_sort];
or
my $slice = sub { \@_ }->( grep { !/^#/ } @array );
@$slice[0..$#$slice] = sort @$slice;
(Unfortunately, @$slice = sort @$slice;
doesn't work —It replaces the elements of @$slice
rather than assigning to them— but a suitable alternative was found.)
Extract the elements to be sorted, then update the original array with the sorted elements:
my @stooges = qw( Larry #Curly Moe Iggy );
my @sorted_items = sort grep { not /^#/ } @stooges;
my @sorted_stooges = map { /^#/ ? $_ : shift @sorted_items } @stooges;
say for @sorted_stooges;
In their answer, @ikegami suggests a variant of this approach where the indexes of the elements to be sorted are extracted, rather than the elements themselves. That solution allows the array elements to be exchanged elegantly with a list slice.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With