in reply to Regex Substring SORT Conundrum

Those posts really are what you need, the Schwartzian Transform. You've just got a more complicated use case. First you'll want to map all the fields that you want to sort on
map { /^(.*)(?>(?:\s.{1,5}(:\d+)*.*))/; [$_, $sortdata{$1}, $2, $3] }
(I haven't checked the correctness of the regex)

then the sort becomes as easy as

sort { $a->[1] <=> $b->[1] || $a->[2] <=> $b->[2] || $a->[3] <=> $b->[ +3] }
and then remap the values with map { $_->[0] }. This of course is done in reverse order, but right to left is how I think of constructing the Transform.

Does that make sense?

Sometimes I can think of 6 impossible LDAP attributes before breakfast.

Replies are listed 'Best First'.
Re^2: Regex Substring SORT Conundrum
by Polyglot (Chaplain) on Mar 05, 2015 at 16:45 UTC

    I guess map is where my weakness lies. If only I could understand it. There are some things I've never been able to grasp, it seems. Things like map, grep, and, above all, object references would be at the top of the list. I'm thankful that I seem to have had no trouble understanding regex. Thank you for your pointers, though; I really appreciate all the helpfulness here.

    Blessings,

    ~Polyglot~

      map is a transforming filter: it takes the right side (after the code block), transforms it according to the code block, and spits the transformed pieces out the other side. Think of it like an assembly line:

      • a bin of widgets is dumped into the hopper at the beginning of the line
      • A whatzit is added to the widget to make a whatever
      • a bin of whatevers is left at the end of the line.

      Does that help explain it at all?

      --MidLifeXis

      It's definitely worth the effort. Let me see if I can break down the map I gave (and maybe clean it up a bit). Starting from
      map { /^(.*)(?>(?:\s.{1,5}(:\d+)*.*))/; [$_, $sortdata{$1}, $2, $3] }
      you should read it like
      map { my ($book, $chapter, $verse) = /^(.*)(?>(?:\s.{1,5}(:\d+)*.*))/; + [$_, $sortdata{$book}, $chapter, $verse] }
      (I'm taking for granted that your regex works like that) For each element of your list, it
      1. assigns the element to $_
      2. applies the regex and assigns the captures to ($book, $chapter, $verse)
      3. creates an anonymous array [ ] with the original element at index 0 and the other 3 which you'll use in the sort
      4. passes it on to the next process
      so from your first list, you get a list of anonymous arrays for your sort which you can reference using $_->2 for the chapter, etc. Also remember that $a->[1] <=> $b->[1] sorts numerically while $a->[1] cmp $b->[1] sorts alphabetically. The map on the other side of the sort takes the list of sorted anonymous arrays and reduces it to the original elements, now sorted.

      A better explanation of the Transform is in the Modern Perl book

      Sometimes I can think of 6 impossible LDAP attributes before breakfast.