2

Suppose you have a list, with each element an ordered pair {a,b} We want to create a new list where each element {a,b} is replaced by {a+b,a-b}

If the original list has three or more ordered pairs, the following works:

list1 = {{a, b}, {c, d}, {e, f}}; (* This list has three ordered pairs *)

list1 /. {x_, y_} -> {x + y, x - y}

The output is, as expected: {{a + b, a - b}, {c + d, c - d}, {e + f, e - f}}

However, if the list has ONLY TWO ordered pairs, the above procedure doesn't seem to work, as shown below:

list2 = {{a, b}, {c, d}}; (* This list has ONLY TWO ordered pairs *)

list2 /. {x_, y_} -> {x + y, x - y}

The output is, unexpectedly(?) {{a + c, b + d}, {a - c, b - d}} Can someone please tell me why this doesn't work? I would appreciate any insight.

I know I can do something like the following to get the desired result:

Cases[list2, {x_, y_} -> {x + y, x - y}]

Thank you very much!

ciao
  • 25,774
  • 2
  • 58
  • 139
user6009
  • 151
  • 5

2 Answers2

5

ReplaceAll scans the expression starting with the outermost level, working its way inwards.

Therefore, in your example, x_ will match {a,b} and y_ will match {c,d}.

This is an extremely common mistake, and it is why I never use ReplaceAll to process a list of elements. Use Replace instead, and indicate that it should only work at level {1}, i.e. process the elements of the list one-by-one.

Replace[list1, {x_, y_} -> {x + y, x - y}, {1}]
Szabolcs
  • 234,956
  • 30
  • 623
  • 1,263
3

Another way to do it:

x = π;
list1 = {{{a, b}, {c, d}}, {e, f}}; (* non-rectangular array *)
list2 = {{a, b}, {c, d}};
list3 = {{a, b}};
list4 = {a, b};

list1 /. {x_, y_}?VectorQ :> {x + y, x - y} list2 /. {x_, y_}?VectorQ :> {x + y, x - y} list3 /. {x_, y_}?VectorQ :> {x + y, x - y} list4 /. {x_, y_}?VectorQ :> {x + y, x - y}

Note the use of :> instead of -> is required, since x has a value.

LouisB
  • 12,528
  • 1
  • 21
  • 31