2

So, for example i have array like that:

my @arr = (
"blabla\t23\t55",
"jkdcbx\t55\t89",
"jdxjcl\t88\t69",
......)

And i need to sort this array by second column after \t, without outer splits. Is it possible to do?

3
  • 1
    "without outer splits" What do you mean by that? Commented Mar 24, 2017 at 12:12
  • 1
    "sort this array by second column after \t" Do you mean the third column? Commented Mar 24, 2017 at 12:14
  • What have you tried? What problems are you having? Commented Mar 24, 2017 at 13:21

3 Answers 3

4

May be a more elegant way but this will work :

my @arr = ( "blabla\t23\t55", "jkdcbx\t55\t89", "jdxjcl\t88\t69");
for (sort {(split(/\t/,$a))[2] <=> (split(/\t/,$b))[2]} @arr) {
    print "$_\n";
}
Sign up to request clarification or add additional context in comments.

2 Comments

Your code is elegant, but I was curious if there was a faster way to sort, as it seems like you run the split code more than is needed. The following code on a big data set takes 8 seconds compared to 19 seconds for your way. my %arr_assoc; my @arr = ( "blabla\t23\t55", "jkdcbx\t55\t89", "jdxjcl\t88\t69"); for (@arr) {$a = (split(/\t/))[2]; $arr_assoc{$_}=$a} for (sort {$arr_assoc{$a} <=> $arr_assoc{$b}} keys %arr_assoc) {print "$_\n"}
@EricKlien yes much improved, thanks.
2

Update

I've just realised that your question may mean that you want to sort by the third column instead of the second

That would be done by using

my ($aa, $bb) = map { (split /\t/)[2] } $a, $b;

instead

output

blabla  23  55
jdxjcl  88  69
jkdcbx  55  89



I always prefer to use map to convert the values from the original data into the function that they should be sorted by

This program demonstrates

I assume you want the values sorted numerically? Unfortunately your example data is already sorted as you describe

use strict;
use warnings 'all';
use feature 'say';

my @arr = (
    "blabla\t23\t55",
    "jkdcbx\t55\t89",
    "jdxjcl\t88\t69",
);


my @sorted = sort {
    my ($aa, $bb) = map { (split /\t/)[1] } $a, $b;
    $aa <=> $bb;
} @arr;

say for @sorted;

output

blabla  23  55
jkdcbx  55  89
jdxjcl  88  69

Comments

1

Try this

use warnings;
use strict;
no warnings "numeric";

my @arr = (
"blabla\t23\t55",
"jkdcbx\t85\t89",
"jdxjcl\t83\t69",
);

my @result = sort {$a=~s/^[^\t]*\t//r <=> $b=~s/^[^\t]*\t//r } @arr;

$, = "\n";

print @result,"\n";

I have used following technique with sort for to do it

Negation character class

Non-destructive modifier(-r) - perform non-destructive substitution and return the new value

And tured of the warning for numeric

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.