Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I have a matrix made mostly from "x" with a few 0's thrown in:

list = {{0, "x", "x", 0}, {0, "x", "x", "x"}, {0, "x", "x", 
   "x"}, {"x", "x", "x", "x"}, {"x", "x", "x", "x"}, {"x", "x", "x", 
   "x"}, {"x", "x", "x", "x"}, {"x", "x", "x", "x"}, {0, "x", "x", 
   "x"}}

I know that there are 31 "x"'s in the matrix, and I want to replace each of them with a numbered variable: x1, x2, and so on til x31 (without quotations). Here's the expected result:

(* {{0, x1, x2, 0}, {0, x3, x4, x5}, {0, x6, x7, x8}, {x9, x10, x11, 
  x12}, {x13, x14, x15, x16}, {x17, x18, x19, x20}, {x21, x22, x23, 
  x24}, {x25, x26, x27, x28}, {0, x29, x30, x31}} *)

Below is the list of the numbered variables that you may use:

numberedx = Table["x" <> ToString@i // Symbol, {i, Range@Count[list, "x", {2}]}]
(* {x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, 
x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, 
x21, x22, x23, x24, x25, x26, x27, x28, x29, x30, x31} *)

I can't for the life of me figure out how to do this. My gut tells me that some procedural method is in order since each "x" is replaced by its numbered form, then the next "x" down the line is replaced by the next member in the list of numbered variables. Unfortunately I'm very uncomfortable with procedural programming. I also tried MapIndexed but the 0's are mapped as well. I'd really appreciate any help or insight.

share|improve this question

4 Answers 4

up vote 6 down vote accepted

ReplaceAll solution:

i = 1;
list /. "x" :> Symbol@StringJoin["x", ToString[i++]]

The same thing can be achieved with Map:

i = 1;
Map[If[# == "x", "x" <> ToString[i++] // Symbol, #] &, list, {2}]

They both give:

{{0, x1, x2, 0}, {0, x3, x4, x5}, {0, x6, x7, x8}, {x9, x10, x11, 
      x12}, {x13, x14, x15, x16}, {x17, x18, x19, x20}, {x21, x22, x23, 
      x24}, {x25, x26, x27, x28}, {0, x29, x30, x31}}
share|improve this answer

Pickett's answer should get the job done but I encourage you to use indexed objects:

Module[{i = 0},
  list /. s_String :> x[++i]
]
share|improve this answer
    
I'm not sure why the replacement would not stop after the first "x" is replaced by x1. Does the ++ have anything to do with it? –  seismatica Aug 8 at 21:04
    
@seismatica I don't know why you think only the first "x" would be replaced. /. is ReplaceAll. ++i is used to increment a counter with each replacement that is made. (Or each replaced expression that evaluates, to be more correct.) I am sorry if that is not helpful, but I don't understand your confusion so I find it hard to address. –  Mr.Wizard Aug 8 at 21:08
    
For some reason I thought I have to use //. because sometimes /. might only replace the first instance. I guess that's the problem only for significant replacements that alters large interconnected parts of the expression, so it wouldn't be the problem here as only a single x is replaced. –  seismatica Aug 8 at 21:20
    
@seismatica It is not really about "large interconnected parts" but: (1) simple precedence of rules and (2) direction of traversal. By the first I mean something like this: {1, 1, 1} /. {_Integer -> 1, 1 -> 2} where 2 will never appear in the output because the first rule will match anything that the second will and it is applied first. //. will not change that. By the second I mean e.g. {1, 2, 3} //. {x_Integer :> x + 1, x_List :> Mod[x, 2]}. Here the entire expression is tested and found to match the second rule; the first rule is not also applied to the replaced expression. –  Mr.Wizard Aug 9 at 2:40

Another way:

Module[{i = 0, l = #, f}, 
   f[x_String] := Symbol[x <> ToString[++i]];
   f[x_] := x;
   Map[f, l, {2}]] &@list
{{0, x1, x2, 0}, {0, x3, x4, x5}, {0, x6, x7, x8}, {x9, x10, x11, x12},
 {x13, x14, x15, x16}, {x17, x18, x19, x20}, {x21, x22, x23, x24},
 {x25, x26, x27, x28}, {0, x29, x30, x31}}
share|improve this answer

I worked out a solution using Position and a Table of Set's i.e. "set x at this position to the numbered variable with the same index i". I really appreciate all of your answers, and hopefully I will get used to using ++i in the future.

Clear[replacex]
replacex[l_List] := Module[{lCopy = l, positionx, numberedx},
  positionx = Position[l, "x"]; 
  numberedx = Table[Symbol["x" <> ToString[i]], {i, Range[Count[l, "x", {2}]]}]; 
  Table[lCopy[[Sequence @@ positionx[[i]]]] = numberedx[[i]], {i, Length[numberedx]}];
  lCopy]

replacex[list]
(* {{0, x1, x2, 0}, {0, x3, x4, x5}, {0, x6, x7, x8}, {x9, x10, x11, 
  x12}, {x13, x14, x15, x16}, {x17, x18, x19, x20}, {x21, x22, x23, 
  x24}, {x25, x26, x27, x28}, {0, x29, x30, x31}} *)

I also found that these work to replace the second to last line in my module:

Function[i, lCopy[[Sequence @@ positionx[[i]]]] = numberedx[[i]]] /@ Range@Length[numberedx];
Set[lCopy[[Sequence @@ positionx[[#]]]], numberedx[[#]]] & /@ Range@Length[numberedx];

but not this

(lCopy[[Sequence @@ positionx[[#]]]] = numberedx[[#]] &) /@ Range@Length[numberedx];

Mathematica graphics

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.