Re: addressing matrix elements
- To: mathgroup at smc.vnet.net
- Subject: [mg3581] Re: addressing matrix elements
- From: villegas (Robert Villegas)
- Date: Wed, 27 Mar 1996 03:25:33 -0500
- Organization: Wolfram Research, Inc.
- Sender: owner-wri-mathgroup at wolfram.com
In article <4itopk$v8 at dragonfly.wolfram.com> drc at emi.net (David Cabana) writes: > Say M is a matrix of integers. I want to func[M, k] to return a matrix > same dimensions as M, each entry consisting of the corresponding entry of > M taken modulo k. For instance, func[{{22,33}, {44,55}}, 10] should > return {{2,3}, {4,5}}. I would like this to work for arbitrary > rectangular integer matrices, but am not having much luck. It seems like > this should be easy, but I'm stumped. > > More generally, I would like to be able to apply a function f to each > element in a matrix of arbitrary size and dimensions, without worrying > about the particulars of the matrix representation via lists. I want > func[M, g] to return a matrix of the same size and shape as M, with > elements formed by applying g to corresponding elements of M. Is there > nice way to do this? Seems like some combination of Map, Apply, Thread, > SetAttributes Listable, Outer, etc. could do the job, but I am lost in the > morass of possibilites. Any help would be appreciated. Many of the mathematical commands are Listable, so there is no need to figure out exactly how to apply them inside the list structure. They will automatically go inside lists, and keep doing so until they reach things that aren't lists (numbers or symbols or whatever). For instance, In[1]:= matrix = {{22,33}, {44,55}}; In[2]:= Mod[matrix, 10] Out[2]= {{2, 3}, {4, 5}} If it's one of your own commands, or some built-in command that isn't Listable, that you need to apply to the entries of a matrix, it's easy to hit the entries: just Map at level {2}: In[3]:= Map[f, matrix, {2}] Out[3]= {{f[22], f[33]}, {f[44], f[55]}} As long as all the things you want to hit with f are at the same depth in the list, Map can do what you need. You could hit the entries of a 4D tensor by specifying level {4}. For instance, In[7]:= tensor4 = Array[Plus, {2, 3, 2, 3}]; MatrixForm[tensor4] Out[7]//MatrixForm= 4 5 6 5 6 7 6 7 8 5 6 7 6 7 8 7 8 9 5 6 7 6 7 8 7 8 9 6 7 8 7 8 9 8 9 10 In[8]:= Map[f, tensor4, {4}] //MatrixForm Out[8]//MatrixForm= f[4] f[5] f[6] f[5] f[6] f[7] f[6] f[7] f[8] f[5] f[6] f[7] f[6] f[7] f[8] f[7] f[8] f[9] f[5] f[6] f[7] f[6] f[7] f[8] f[7] f[8] f[9] f[6] f[7] f[8] f[7] f[8] f[9] f[8] f[9] f[10] The expression need not even be a tensor (i.e. have an even rectangular shape); as long as all the elements you want to hit with f are at the same depth. If you have a nested list of uneven depths, for instance In[9]:= expr = {1, {2, {3, 4}, 5}, {{6, 7}, {8, 9, 10}}} Out[9]= {1, {2, {3, 4}, 5}, {{6, 7}, {8, 9, 10}}} and if you want your function f to filter through all the lists and apply itself to things that aren't lists, you could make your function Listable like many of Mathematica's functions are: In[10]:= SetAttributes[f, Listable] In[11]:= f[expr] Out[11]= {f[1], {f[2], {f[3], f[4]}, f[5]}, > {{f[6], f[7]}, {f[8], f[9], f[10]}}} If you don't want g to be Listable in general, but just want to use it in a Listable way from time to time, then you could make a temporary function that applies g to its argument, and has the property of being Listable. Each time you need to use g in a Listable manner, do this: In[13]:= Function[element, g[element], Listable] [expr] Out[13]= {g[1], {g[2], {g[3], g[4]}, g[5]}, > {{g[6], g[7]}, {g[8], g[9], g[10]}}} Robby Villegas ==== [MESSAGE SEPARATOR] ====