4

I want to update a List, using a For-statement. It doesn't work as I expect.

my data is like:

data = {{1, 11, 12, 13}, {1, 14, 15, 16}, {1, 17, 18, 19}, {2, 21, 22,
    23}, {2, 24, 25, 26}, {2, 27, 28, 29}, {3, 31, 32, 33}, {3, 34, 
   35, 36}, {3, 37, 38, 39}};

set = {"A", "B", "C"};

The desired output is:

{{1, 11, 12, 13, A}, {1, 14, 15, 16, A}, {1, 17, 18, 19, A}, {2, 21, 
  22, 23, B}, {2, 24, 25, 26, B}, {2, 27, 28, 29, B}, {3, 31, 32, 33, 
  C}, {3, 34, 35, 36, C}, {3, 37, 38, 39, C}}

My idea was:

For[i = 2, i <= Length[set], i++,
  Map[Append[#, set[[i]]] &, Select[data, #[[1]] == i &]]
  ];

But it does not give te output.

When I do the same

i = 1;
Map[Append[#, set[[i]]] &, Select[data, #[[1]] == i &]]

I get:

{{1, 11, 12, 13, "A"}, {1, 14, 15, 16, "A"}, {1, 17, 18, 19, "A"}}

Can somebody explain the difference and give me suggestion how to improve the FOR-statement (or a another solution te get the desired output.

Jagra
  • 14,343
  • 1
  • 39
  • 81
Michiel van Mens
  • 2,835
  • 12
  • 23
  • 3
    For gives no output. The documentation does not suggest that it would. – Szabolcs Nov 13 '20 at 13:46
  • 3
    If you have not yet seen this, recommended reading: https://mathematica.stackexchange.com/q/134609/12 (i.e., use Table, or explain why you think you need For) – Szabolcs Nov 13 '20 at 13:47
  • Not sure why you wish to remove quotes but if you do, Mathematica will treat them as variables and not good programming practice to start variable names with upper case but you could use ToExpression[set[[i]]] to convert the characters to variables if that's what you want. – Dominic Nov 13 '20 at 14:26

6 Answers6

5

Better ways to do this:

Join[data, List /@ set[[data[[All, 1]]]], 2]

or

Map[Append[#, set[[#[[1]]]]] &, data]
Sjoerd Smit
  • 23,370
  • 46
  • 75
3
f[{a_, b__}, set_: set] := {a, b, set[[a]]}
f /@ data
AsukaMinato
  • 9,758
  • 1
  • 14
  • 40
3
a =
  {{1, 11, 12, 13}, {1, 14, 15, 16}, {1, 17, 18, 19},
   {2, 21, 22, 23}, {2, 24, 25, 26}, {2, 27, 28, 29}, 
   {3, 31, 32, 33}, {3, 34, 35, 36}, {3, 37, 38, 39}};

set = {"A", "B", "C"};

Using MapThread and Partition

Catenate @ MapThread[Append[#1] /@ #2 &, {set, Partition[a, 3]}] // MatrixForm

enter image description here

The above solution works with any first elements:

b =
  {{1, 11, 12, 13}, {2, 14, 15, 16}, {3, 17, 18, 19}, 
   {4, 21, 22, 23}, {5, 24, 25, 26}, {6, 27, 28, 29}, 
   {7, 31, 32, 33}, {8, 34, 35, 36}, {9, 37, 38, 39}};

Catenate @ MapThread[Append[#1] /@ #2 &, {set, Partition[b, 3]}] // MatrixForm

enter image description here

eldo
  • 67,911
  • 5
  • 60
  • 168
2

Some more ways to do this:

data = {{1, 11, 12, 13}, {1, 14, 15, 16}, {1, 17, 18, 19}, {2, 21, 22,
     23}, {2, 24, 25, 26}, {2, 27, 28, 29}, {3, 31, 32, 33}, {3, 34, 
    35, 36}, {3, 37, 38, 39}};
set = {"A", "B", "C"};
Cases[data, {a_, b__} :> {a, b, set[[a]]}]
data /. {a_, b_, c_, d_} :> {a, b, c, d, set[[a]]}
Table[Append[item, set[[item[[1]]]]], {item, data}]
newdata = data;
For[n = 1, n <= Length[data], n++,
 newdata[[n]] = Append[data[[n]], set[[data[[n, 1]]]]]
 ]
newdata
MelaGo
  • 8,586
  • 1
  • 11
  • 24
2
data = {{1, 11, 12, 13}, {1, 14, 15, 16}, {1, 17, 18, 19}, {2, 21, 22,
     23}, {2, 24, 25, 26}, {2, 27, 28, 29}, {3, 31, 32, 33}, {3, 34, 
    35, 36}, {3, 37, 38, 39}};

set = {"A", "B", "C"};

The question can be interpreted as follows such that the inclusion of information in set is not required.

data /. x_?VectorQ :> Append[x, ToUpperCase@Alphabet[][[First@x]]]

For a different ordering in set, however, the following would perhaps be more robust.

data /. x_?VectorQ :> Append[x, set[[First@x]]]

comment

The question suffers from it not being narrowly specified and hence open to interpretation. A better data would be one with sublists scrambled with respect to the first element and some indication of the relation between data and set.

Syed
  • 52,495
  • 4
  • 30
  • 85
2
a =
  {{1, 11, 12, 13}, {1, 14, 15, 16}, {1, 17, 18, 19},
   {2, 21, 22, 23}, {2, 24, 25, 26}, {2, 27, 28, 29}, 
   {3, 31, 32, 33}, {3, 34, 35, 36}, {3, 37, 38, 39}};

set = {"A", "B", "C"};

Using Replace at level 1:

Replace[a, {a_, b__} :> {a, b, set[[a]]}, {1}] //MatrixForm

enter image description here

E. Chan-López
  • 23,117
  • 3
  • 21
  • 44