4
$\begingroup$

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.

$\endgroup$
3
  • 3
    $\begingroup$ For gives no output. The documentation does not suggest that it would. $\endgroup$
    – Szabolcs
    Nov 13, 2020 at 13:46
  • 3
    $\begingroup$ If you have not yet seen this, recommended reading: mathematica.stackexchange.com/q/134609/12 (i.e., use Table, or explain why you think you need For) $\endgroup$
    – Szabolcs
    Nov 13, 2020 at 13:47
  • $\begingroup$ 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. $\endgroup$
    – Dominic
    Nov 13, 2020 at 14:26

6 Answers 6

5
$\begingroup$

Better ways to do this:

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

or

Map[Append[#, set[[#[[1]]]]] &, data]
$\endgroup$
3
$\begingroup$
f[{a_, b__}, set_: set] := {a, b, set[[a]]}
f /@ data
$\endgroup$
3
$\begingroup$
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

$\endgroup$
2
$\begingroup$

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
$\endgroup$
2
$\begingroup$
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.

$\endgroup$
2
$\begingroup$
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

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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