in reply to Transposing 2 dimensional arrays

Here's my version that's a little more perlish as you'd say.:

use Data::Dumper; use strict; use warnings; sub pivot { my @src = @_; my $max_col = 0; $max_col < $#$_ and $max_col = $#$_ for @src; my @dest; for my $col (0..$max_col) { my @new_row; for my $row (0..$#src) { push @new_row, $src[$row][$col] // ''; } push @dest, \@new_row; } return @dest; } my @test = ( [1..5], [11..15], [21..25], [31..35], [41], [51..55], ); my @results = pivot(@test); print Dumper(\@results); =prints $VAR1 = [ [1,11,21,31,41,51], [2,12,22,32,'',52], [3,13,23,33,'',53], [4,14,24,34,'',54], [5,15,25,35,'',55] ]; =cut

Update: And a little more perlish still would be to use map:

sub pivot { my @src = @_; my $max_col = 0; $max_col < $#$_ and $max_col = $#$_ for @src; my @dest; for my $col (0..$max_col) { push @dest, [map {$src[$_][$col] // ''} (0..$#src)]; } return @dest; }

This last is actually my preferred way of doing this, since it's easy to see what the inner loop is iterating on.

- Miller

Replies are listed 'Best First'.
Re^2: Pivoting 2 dimensional array refs
by choroba (Cardinal) on May 13, 2011 at 08:38 UTC
    Your results are different from the results of the original sub:
    $VAR1 = [ [1,11,21,31,41,51], [2,12,22,32,'',52], [3,13,23,33,'',53], [4,14,24,34,'',54], [5,15,25,35,'',55] ];
    Update: They are not, you just did not update the pod :)
Re^2: Pivoting 2 dimensional array refs
by John M. Dlugosz (Monsignor) on May 14, 2011 at 10:53 UTC
    Nice. It's fundimentally the same, but you get a lot of collapse of excess code by folding up the if/else decision when computing $value.

    I would normally, in any language, spot that construct:

    if (something) value = xxxxx else value = yyyy
    as something to be folded up into one expression. Perhaps a terinary operator: value = (something) ? xxxxx : yyyy. But the "defined or" really shines here, reeling in the rest. That is precisely the idiom that the OP needs in the problem: grab the value at the source coordinates, but make it '' instead of undef.

    I see that the computation of max_col was made into one line by using the suffix form of 'for'. That shrunk the vertical expanse of code down quite a bit.

      I once thought as you do ;).

      Unless there is a performance gain that is:

      1. Truly significant
      2. Actually needed
      I stay away from ternary assignment and other forms of code collapse in favor of more verbose easy to read code. I'd far rather opt for clear suboptimal code than optimized idioms that don't really give me much.

      Now if there's actual redundancy I'm more inclined to squnch it up.

      But I suspect this largely talks past your point of the 'defined or' which, as I'm packing, I haven't yet had time to cogitate over.

      o/

      Me
        More verbose doesn't mean easier to read. The separate branches means I have to read through and grasp that the LHS is the same, and then re-arrange it in my mind to the higher-level idea: set LHS to one of two things depending on condition.

        Writing the more concise form more closely represents the higher-level meaning. That doesn't mean you have to make it overly terse: write it on separate lines:

        $value= (condition) ? this : that ;
        It's no different than using a for loop instead of a while, to put the different parts of the idiom together.

        For sequential steps, I'll certainly write it on multiple lines with named variables for the intermediate values, rather than cramming it into one huge nested statement. But this is not like that. Spreading it out makes it harder to read.

        More specialized forms, like the one he used (//), are idiomatic in Perl. open or die. $normal // $blank.

        You say "optimized idioms". Well, I think we are speaking across purposes. Nesting a bunch of stuff instead of writing separate statements doesn't make it any clearer. But using a well-known idiom gives a higher-level impression of its meaning, what it's used for and the specific nature of the problem it is addressing.

        If you don't know them yet, sure they are confusing because the writer doesn't need to comment in detail what those issues and solved problems are — the use of the idiom says it all. But once you learn why a particular twist of the keyboard is written that way, maybe read a whole essay about it, then you just follow that example and consider the matter settled.

        As for cocnating the "defined or", you might want to start with the regular logical || and its low-precedence counterpart or. Look how it's different from C, in that the result of the expression isn't just "true" but the value from the first true argument. They are used tersely like footnotes: if that normal way didn't work out, use this instead. Or as control-flow, picking the first one that applies.

        If I have a parameter $x, and the caller can leave off the parameter and mean the default value of 42, you can write, in the body of the function $x//42. Or you can set it if it's not passed, with $x //= 42;. The pulling of the data from the matrix with missing values is the same: give me xy, but if that's not available, use blank instead.

        The code you learned for opening files uses this kind of control flow too:

        open FILE, '<', $fname or die "Can't open $fname";

        Are you really saying that you find

        if( cond ) { $var = val1; } else { $var = val2; }

        Substantially clearer or easier to code or understand than

        $var = cond ? val1 : val2;
        ?

        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.
Re^2: Pivoting 2 dimensional array refs
by Voronich (Hermit) on May 13, 2011 at 13:07 UTC
    Hey nice. Thanks for that. I'll have to sit down with a cigar and go over that a bit. Your assignment of max_col is somewhat dizzying. Would this handle an empty subordinate array? (eh, nm. I'll check it out.)
    Me