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.