Re: List Manipulation
- To: mathgroup at smc.vnet.net
- Subject: [mg124973] Re: List Manipulation
- From: Ray Koopman <koopman at sfu.ca>
- Date: Wed, 15 Feb 2012 04:42:27 -0500 (EST)
- Delivered-to: l-mathgroup@mail-archive0.wolfram.com
- References: <jh6k3l$jrc$1@smc.vnet.net>
On Feb 11, 12:46 pm, Murta <rodrigomur... at gmail.com> wrote:
> Hi All
>
> I'm looking some better solution for the below list manipulation:
> l1={a,b,c};
> l2={{1,2,3},{4,5,6},{7,8,9}};
> output = {{a,1},{a,2},{a,3},{b,4},{b,5},{b,6},{c,7},{c,8},{c,9}}
> It's a simple distributions of terms.
>
> I used this solution, but I think it's not an elegant one:
>
> f[a_, b_] := Flatten[{a, #}] & /@ b;
> MapThread[f, {l1, l2}] // Flatten[#, 1] &
>
> Some clue?
> Maybe with Outer or Inner?
> Thanks in advance!
> Murta
This seems as appropriate an occasion as any to sound off about
something that's been bugging me for a while. IMHO, the most elegant
(although perhaps not the most efficient) solution to the problem is
L1 = {a,b,c};
L2 = { {1,2,3}, {4,5,6}, {7,8,9} };
Join @@ Thread /@ Thread @ {L1, L2}
{ {a,1},{a,2},{a,3}, {b,4},{b,5},{b,6}, {c,7},{c,8},{c,9} }
Extending the problem to include cases where the second array may be
ragged, we have
L3 = { {1,2}, {3,4,5}, {6,7,8,9} };
Join @@ Thread /@ Thread @ {L1, L3}
{ {a,1},{a,2}, {b,3},{b,4},{b,5}, {c,6},{c,7},{c,8},{c,9} }
The same code handles both cases.
Now consider code that uses Inner. The following works for
rectangular arrays but not for ragged:
Join @@ Transpose @ Inner[List, L1, L2, List]
{ {a,1},{a,2},{a,3}, {b,4},{b,5},{b,6}, {c,7},{c,8},{c,9} }
Join @@ Transpose @ Inner[List, L1, L3, List]
{ a, b, c, {1,2}, {3,4,5}, {6,7,8,9} }
I have no problem with that. Rectangular is a special case, and
there is nothing strange about code that works in a special case
but fails in more general cases.
However, the following code works for ragged arrays but fails if
the array happens to be rectangular:
Inner[ Thread@{##}&, L1, L3, Join]
{ {a,1},{a,2}, {b,3},{b,4},{b,5}, {c,6},{c,7},{c,8},{c,9} },
Inner[ Thread@{##}&, L1, L2, Join]
{ {a,1,b,4,c,7}, {a,2,b,5,c,8}, {a,3,b,6,c,9} }.
I don't see that as analogous to the failure of division to handle
a zero divisor, or of Dot to handle matrices that are not conformal
for multiplication. Those are cases where the function is naturally
undefined. But here there is no reason why the rectangular case
should be treated specially. Inner arbitrarily *defines* it as
special.
The basic definition of Inner, unchanged since Version 1, is
Inner[f, {a,b,c}, {x,y,z}, g]
g[ f[a,x], f[b,y], f[c,z] ].
The only requirement is that the second and third arguments --
e.g., {a,b,c} and {x,y,z}, in the example -- be lists with the same
lengths.
If x,y,z are themselves lists with different lengths then we have,
for instance,
Inner[f, {a,b,c}, { {x1}, {y1,y2}, {z1,z2,z3} }, g]
g[ f[a,{x1}], f[b,{y1,y2}], f[c,{z1,z2,z3}] ],
which is consistent with the basic definition. However, if x,y,z
happen to have the same lengths then the interpretation changes:
Inner[f, {a,b,c}, { {x1,x2}, {y1,y2}, {z1,z2} }, g]
{ g[f[a,x1], f[b,y1], f[c,z1]], g[f[a,x2], f[b,y2], f[c,z2]] },
which is not always consistent with the basic definition. At the very
least, this should be pointed out in the Possible Issues section of
the documentation for Inner.