9
$\begingroup$

I have a list of lists of equal sizes (odd or even), e.g.

list={{1,-2,3,1,3,4},{3,5,6,-1,9,0},{1,-2,-4,-5,1,5},{1,-1,2,3,5,4},...}

I would like to change signs of every element which is on even or odd position. In the example above, for the choice of change on even positions, it should give the following result:

 listnew={{1,2,3,-1,3,-4},{3,-5,6,1,9,0},{1,2,-4,5,1,-5},{1,1,2,-3,5,-4},...}

What is the most effective way to achieve this? (The length of list may be huge here).

$\endgroup$

7 Answers 7

8
$\begingroup$

MapIndexed can not only extract positions of elements (in Slot 2, always), but also further apply transformations to the elements themselves (Slot 1). So in my opinion, it is the most suitable one to do the job desired:

MapIndexed[(-1)^(#2[[2]] + 1) # &, list, {2}]
$\endgroup$
9
$\begingroup$
list = {{1, -2, 3, 1, 3, 4}, {3, 5, 6, -1, 9, 0}, {1, -2, -4, -5, 1, 
    5}, {1, -1, 2, 3, 5, 4}};
v = {1, -1, 1, -1, 1, -1};
Times[v, #] & /@ list
Outer[Times, {v}, list, 1] // First
$\endgroup$
9
$\begingroup$

Use Part to multiply even positions by -1:

listeven = list =
  {{1, -2, 3, 1, 3, 4}, {3, 5, 6, -1, 9, 0}, 
   {1, -2, -4, -5, 1, 5}, {1, -1, 2, 3, 5, 4}};
listeven[[All, 2 ;; ;; 2]] *= -1;
listeven
(* {{1, 2, 3, -1, 3, -4}, {3, -5, 6, 1, 9, 0},
    {1, 2, -4, 5, 1, -5}, {1, 1, 2, -3, 5, -4}} *)

A small change multiplies the odd positions:

listodd = list =
  {{1, -2, 3, 1, 3, 4}, {3, 5, 6, -1, 9, 0},
   {1, -2, -4, -5, 1, 5}, {1, -1, 2, 3, 5, 4}};
listodd[[All, 1 ;; ;; 2]] *= -1;
listodd
(* {{-1, -2, -3, 1, -3, 4}, {-3, 5, -6, -1, -9, 0},
    {-1, -2, 4, -5, -1, 5}, {-1, -1, -2, 3, -5, 4}} *)
$\endgroup$
7
$\begingroup$

This is one way:

MapIndexed[{n, pos} |-> If[ EvenQ @ Last @ pos, -n, n], list, {2}]
$\endgroup$
7
$\begingroup$

This should be reasonably fast, I think:

list.DiagonalMatrix[{1,-1,1,-1,1,-1}]

{{1, 2, 3, -1, 3, -4}, {3, -5, 6, 1, 9, 0}, {1, 2, -4, 5, 1, -5}, {1, 1, 2, -3, 5, -4}}

list.DiagonalMatrix[{1,-1,1,-1,1,-1}]==listnew

True

Alternatively:

With[{x=Length@list[[1]]}, list.SparseArray[Band[{1, 1},{x,x}] -> {1,-1}]]==listnew

True

where

list={{1,-2,3,1,3,4},{3,5,6,-1,9,0},{1,-2,-4,-5,1,5},{1,-1,2,3,5,4}}
$\endgroup$
2
$\begingroup$
list =
  {{1, -2, 3, 1, 3, 4},
   {3, 5, 6, -1, 9, 0},
   {1, -2, -4, -5, 1, 5},
   {1, -1, 2, 3, 5, 4}};

ChangeSign[m_, s_ : 2] := MapAt[-# &, m, {All, s ;; ;; 2}]

Even positions:

ChangeSign[list]

{{1, 2, 3, -1, 3, -4},
{3, -5, 6, 1, 9, 0},
{1, 2, -4, 5, 1, -5},
{1, 1, 2, -3, 5, -4}}

Odd positions:

ChangeSign[list, 1]

{{-1, -2, -3, 1, -3, 4},
{-3, 5, -6, -1, -9, 0},
{-1, -2, 4, -5, -1, 5},
{-1, -1, -2, 3, -5, 4}}

$\endgroup$
1
$\begingroup$
list =
  {{1, -2, 3, 1, 3, 4},
   {3, 5, 6, -1, 9, 0},
   {1, -2, -4, -5, 1, 5},
   {1, -1, 2, 3, 5, 4}};

Another way using Replace, Table and DiagonalMatrix:

f = DiagonalMatrix[Table[(-1)^(n + 1), {n, #[[-1]] &@Dimensions@#}]] &;

Replace[#, x_ :> x . f@#, 1] &@list // TeXForm

$\left( \begin{array}{cccccc} 1 & 2 & 3 & -1 & 3 & -4 \\ 3 & -5 & 6 & 1 & 9 & 0 \\ 1 & 2 & -4 & 5 & 1 & -5 \\ 1 & 1 & 2 & -3 & 5 & -4 \\ \end{array} \right)$

$\endgroup$

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