Re: Threading objects of unequal length
- To: mathgroup at smc.vnet.net
- Subject: [mg8163] Re: [mg8112] Threading objects of unequal length
- From: Olivier Gerard <jacquesg at pratique.fr>
- Date: Sat, 16 Aug 1997 11:51:07 -0400
- Sender: owner-wri-mathgroup at wolfram.com
C. Woll wrote > Hi group, > > I'm interested in adding variable length List. For example, I would like > to do something like > > {a,b}+{c,d,e}+{f} > > to return > > {a+c+f,b+d,e} > > Of course, Plus doesn't work, since you can't thread objects of unequal > length. > > [ more follows...] For the specific task of Plus, which is very easy to handle because there is a neutral element (namely 0), you can do something like that: PaddedPlus[ jk__List ] := Module[{mlotl}, mlotl=Max[Map[Length, List[jk]]]; Plus@@Map[Join[#1,Array[0&,mlotl-Length[#1]]]&, List[jk]] ] Example: PaddedPlus[ {a,b}, {c,d,e,f},{g,h,i}] {a + c + g, b + d + h, e + i, f} This is only a rough interpretation, mostly valable for sets of lists irregular only at the first level. For more nested cases, one should be a bit more cautious and imaginative. Also, the reason why Thread does not do something like this is that many behaviors are possible in this situation. (By the way, my code is easy modifiable to the case were you want the lists to be justified to the right instead of the left or even to a few differents kind of centering). > So what is a good way of defining a function to do this? To be specific, I > would like a function g which accepts multiple arguments, and when given > an input like > > g[{a,b}, {c,d,e}, {f}] > > returns > > {h[a,c,f],h[b,d],h[e]} > > where in my particular application, I want h to be Plus. However, it would > be nice to have the function work for arbitrary heads. > > I could do something like padding each of the arguments with some dummy > variable so that everything has the same length, then threading, then > removing the dummy variable, but that seems very cumbersome. Can anyone > think of a better way? > > Thanks for any comments. > > Carl Woll > Physics Dept > U of Washington A good way in my opinion would be to have a very powerful syntax for a generalization of Transpose and a neutral element for being in a list or for list ap/pre-pending. I have been proposing that many times to WRI. Anyone listening ? Here is an easy implementation of the idea you mention, restricted to your original purpose and you can see it is not so cumbersome: (* Code *) Clear[NotAnElt]; TestEltQ[NotAnElt] = False; TestEltQ[__] = True; SetAttributes[PaddedThread, HoldAll] PaddedThread[ hd_Symbol[jk__List] ] := Module[{mlotl=Max[Map[Length, List[jk]]]}, Map[ hd@@Select[#1,TestEltQ]&, Transpose[Map[Join[#1,Array[NotAnElt&,mlotl-Length[#1]]]&, List[jk]]] ] ] (* Example *) PaddedThread[ FTGT[{a,b}, {c,d,e,f},{g,h,i}] ] {FTGT[a, c, g], FTGT[b, d, h], FTGT[e, i], FTGT[f]} This 'version' of Thread has not all the features of the original but it would not be difficult to make it so. We can imagine an option with values Left, Right for the kind of padding and a few other things. Another way of doing what you want to do is to play with indices of elements in the lists. It is often inefficient in Mathematica compared to List programming. I would be very interested if someone has another idea. Of course, the ideas I alluded to have broader uses and could be a significant addition to Mathematica programming language but to be implemented both generally and efficiently they require more code and intermediate functions to help users master their power. Hope this helps, Olivier Gerard Mathematica Developper