Schwartzian transform

Alex Balhatchet kaoru at slackwise.net
Wed Aug 13 10:50:39 BST 2014


Hi Dermot,

You have a few problems with your code:

1. First argument to map is a block

You should be wrapping your code block to map with curly braces.

eg. map { [ $_, $ref->{$_}{position} ] }

2. No need to use $ref in your second (chronologically by execution,
first by line number) map

The Schwartzian Transform puts the original value into the first
element of the array reference, so to map back you just take $_->[0].

3. Some mis-placed commas

When chaining maps and sorts you don't need commas, because there
should be no comma separating your block from the next argument to map
(this is related to my first point.)

================

Put it all together:

#!/usr/bin/env perl

use strict;
use warnings;
use Data::Dumper;

my $ref = {
    '603927' => {
        'title' => 'Light and healthy picnic food',
        'position' => 2,
        'license' => 'F',
        'id' => '603927'
    },
    '562734' => {
        'license' => 'M',
        'position' => '0',
        'title' => 'Man and woman beside highland loch in rai',
        'id' => '562734',
    },
    '569368' => {
        'license' => 'F',
        'position' => '1',
        'title' => 'A wooden picnic bench on the sand',
        'id' => '569368',
        'thumb' => '/image/569368/thumb'
    },
    '193246' => {
        'license' => 'F',
        'position' => '5',
        'title' => 'A wooden picnic bench on the sand',
        'id' => '193246',
        'thumb' => '/image/569368/thumb'
    }
};

print Dumper ($ref);

my @sorted =
    map { $_->[0] }
    sort { $a->[1] <=> $b->[1] }
    map { [ $_, $ref->{$_}{position} ] }
    keys %{ $ref };

print Dumper (\@sorted);

================

I can also recommend looking at Sort::Key which does this for you, and
avoids the need for messing around with $a and $b.

#!/usr/bin/env perl

use strict;
use warnings;
use Data::Dumper;
use Sort::Key qw(ikeysort);

my $ref = {
    '603927' => {
        'title' => 'Light and healthy picnic food',
        'position' => 2,
        'license' => 'F',
        'id' => '603927'
    },
    '562734' => {
        'license' => 'M',
        'position' => '0',
        'title' => 'Man and woman beside highland loch in rai',
        'id' => '562734',
    },
    '569368' => {
        'license' => 'F',
        'position' => '1',
        'title' => 'A wooden picnic bench on the sand',
        'id' => '569368',
        'thumb' => '/image/569368/thumb'
    },
    '193246' => {
        'license' => 'F',
        'position' => '5',
        'title' => 'A wooden picnic bench on the sand',
        'id' => '193246',
        'thumb' => '/image/569368/thumb'
    }
};

print Dumper ($ref);

my @sorted = ikeysort { $ref->{$_}{position} } keys %$ref;

print Dumper (\@sorted);

================

See https://metacpan.org/pod/Sort::Key for more info on that one.

- Alex

On 13 August 2014 10:33, Dermot <paikkos at gmail.com> wrote:
> Hi
>
> Sorry for the OT post :)
>
> I am trying to transform the hash reference below so that the value of
> position is ordered from 1..4. The sorting works but I can't seem to modify
> the value of {position} inline. To achieve what I want I have to look
> through the @sorted array. I'd like to golf this if I can but I've hit a
> wall.
>
> Any suggestions?
> Thanks,
> Dermot.
>
>
>
>
> use strict;
> use warnings;
> use Data::Dumper;
>
> my $ref = {
>           '603927' => {
>                          'title' => 'Light and healthy picnic food',
>                          'position' => 2,
>                          'license' => 'F',
>                          'id' => '603927'
>                        },
>           '562734' => {
>                          'license' => 'M',
>                          'position' => '0',
>                          'title' => 'Man and woman beside highland loch in
> rai',
>                          'id' => '562734',
>                        },
>           '569368' => {
>                          'license' => 'F',
>                          'position' => '1',
>                          'title' => 'A wooden picnic bench on the sand',
>                          'id' => '569368',
>                          'thumb' => '/image/569368/thumb'
>                        },
>            '193246' => {
>                          'license' => 'F',
>                          'position' => '5',
>                          'title' => 'A wooden picnic bench on the sand',
>                          'id' => '193246',
>                          'thumb' => '/image/569368/thumb'
>                        }
> };
>
> print Dumper ($ref);
>
> my @sorted =
>     map $ref->{$_->[0]},
> #    map { $ref->{ $_->[0] }->{position} => $count++ }
>     sort { $a->[1] <=> $b->[1] }
>     map [ $_, $ref->{$_}->{position} ],
>     keys %{ $ref };
>
> print Dumper (\@sorted);
>
> my $count = 1;
> foreach my $hashref (@sorted) {
>     $ref->{ $hashref->{id} }->{position} = $count++;
> }
> print Dumper ($ref);


More information about the london.pm mailing list