0

Is there a way that I can sort an array based on a sub-string of the array element. For example, lets say I have the following array:

@myArray = qw("AAA|111|bbb" "CCC|333|ddd" "EEE|444|fff" "GGG|222|hhh");

I want to sort this array based on the sub-string starting at position 4 (zero-based) for a length of 3 (in the first array element in my example, that would be "111").

The length of each array element will always be the same for all elements and the sub-string I want to sort on will always be in the same position for the same length in the array element.

This is what my sorted output would look like:

AAA|111|bbb

GGG|222|hhh

CCC|333|ddd

EEE|444|fff

Also, while I am showing numbers as the sub-string in my example, it could be non-number values in there too. So the sort would have to work for non-numbers too.

0

2 Answers 2

1

sort can take the first parameter that is a code block that compares two elements:

#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };

my @myArray = qw( AAA|111|bbb CCC|333|ddd EEE|444|fff GGG|222|hhh );


say for sort { substr($a, 4, 3) cmp substr($b, 4, 3) } @myArray;

See also substr.

Note that I removed the double quotes from the qw(). "qw" stands for "quote words", so no quotes are needed (in fact, they would be part of the strings which isn't what you wanted).

Using the Sort::Key module, it can get even simpler:

use Sort::Key qw{ keysort };
...
say for keysort { substr $_, 4, 3 } @myArray;
Sign up to request clarification or add additional context in comments.

Comments

0

What's the use of pipes if this is a record of fixed-length fields?

If you were to treat the input as pipe-separated values, then your code would become

say for sort { ( split /\|/, $a )[1] <=> ( split /\|/, $b )[1] } @myArray;

and

use Sort::Key qw( ikeysort );

say for ikeysort { ( split /\|/ )[1] } @myArray;

[This is not meant to be a complete answer, but an extension of choroba's.]

2 Comments

Thanks Choroba, I will try out your code and get back to you. ikegami, I didn't intend for the array element to resemble a fixed-length record but you are right, it is now and I can remove the pipes. I was so involved in writing my code I didn't realize what had transpired. Thanks for the heads-up. Angelo
You'll find pack "a3 a3 a3" and unpack "a3 a3 a3" useful

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.