http://qs321.pair.com?node_id=1103695


in reply to schwartzian transform

Your problem is in the first map (or the last map reading left to right which is not how I think when I'm building a Schwartzian transform). The /.+,/ in
map { [ $_, /.+,/ ] }
is only returning the number of matches (or 1 in this case). As a result it should give you back the original list. If you're trying to sort on computed fields, you need to extract them first and _then_ bundle them up in the anonymous array.

So something like
map     { my @fields = split /,/; [ $_, $field[1] ] } might get you closer to what you're looking for.

Once you've mastered that, you'll next want to look at the Orcish manoeuvre which speeds up your sorts

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

Replies are listed 'Best First'.
Re^2: schwartzian transform
by Laurent_R (Canon) on Oct 14, 2014 at 09:41 UTC
    I don't really see how an Orcish manoeuvre would improve a Schwartzian Transform sort.

      In this particular case, I'm not sure it would. In general, it can, in situations where the (chronologically) first transform consumes a lot of time for some reason, if you have duplicated data in the list that you are sorting. Not needing to perform the same time-intensive computation repeatedly saves time. But in this case, it doesn't look like there are going to be a lot of duplicate data (though only someone with access to the original poster's real data could say that for sure), and furthermore that regular expression in the first transform doesn't look like it would be much of a bottleneck, so I'm not sure much if anything would be gained.

      You're right, Laurent. You only calculate the sort value once in the first call to map, so there's no savings to be made by caching.

      Those two techniques must be stored together in the "neat things to use with sort" area of my brain. Apologies.

      Sometimes I can think of 6 impossible LDAP attributes before breakfast.
Re^2: schwartzian transform
by AnomalousMonk (Archbishop) on Oct 14, 2014 at 14:49 UTC
    The /.+,/ ... is only returning the number of matches ...

    Not that it makes any difference (the logic is still wrong), but it's returning the success of the match:

    c:\@Work\Perl>perl -wMstrict -MData::Dump -le "my @strings = ('x,x', 'yy,yy,yy', 'z,zzz,z,zz', 'foo'); ;; my @ra = map { [ $_, /[xyz]+,/ ] } @strings; dd \@ra; ;; @ra = map { [ $_, /[xyz]+,/g ] } @strings; dd \@ra; ;; @ra = map { [ $_, scalar(/[xyz]+,/) ] } @strings; dd \@ra; ;; dd \@strings; " [["x,x", 1], ["yy,yy,yy", 1], ["z,zzz,z,zz", 1], ["foo"]] [ ["x,x", "x,"], ["yy,yy,yy", "yy,", "yy,"], ["z,zzz,z,zz", "z,", "zzz,", "z,"], ["foo"], ] [["x,x", 1], ["yy,yy,yy", 1], ["z,zzz,z,zz", 1], ["foo", ""]] ["x,x", "yy,yy,yy", "z,zzz,z,zz", "foo"]
    See Regexp Quote-Like Operators (in perlop) -> /PATTERN/msixpodualgc -> "Matching in list context".

    Update: Edited code example for space.