9
$\begingroup$

Given the two lists below, is there an in-built command or otherwise neat way of accomplishing the desired output.

list = {{1, 2}, {5, 2}, {9, 3}, {6, 5}};
x = {x1, x2, x3, x4, x5, x6, x7};
desiredOutput = {{1, 2, x1}, {5, 2, x2}, {9, 3, x3}, {6, 5, x4}};

My attempt seems ugly:

{list[[#]][[1]], list[[#]][[2]], x[[#]]} & /@ (list // Length // Range)
$\endgroup$
2
  • $\begingroup$ closely related: 51407 $\endgroup$
    – Kuba
    Jun 21, 2016 at 11:00
  • $\begingroup$ Also related: (189), (13748), (14494) $\endgroup$
    – Mr.Wizard
    Jun 21, 2016 at 11:09

11 Answers 11

14
$\begingroup$

Example

Code

list = {{1, 2}, {5, 2}, {9, 3}, {6, 5}};
x = {x1, x2, x3, x4, x5, x6, x7};

MapThread[Append, {list, x[[;; Length  @ list]]}]

Output

{{1, 2, x1}, {5, 2, x2}, {9, 3, x3}, {6, 5, x4}}

Reference

Append
MapThread

$\endgroup$
3
  • $\begingroup$ Why does MapThread[Append, {list, x[[;; Length @ list]]}] work but not MapThread[Append, {list, x[[;; list // Length]]}] work? Even though list // Length and Length@list give the same result? $\endgroup$
    – Tom
    Jun 21, 2016 at 11:10
  • 1
    $\begingroup$ @Tom consider ;; list // Length and ;; (list // Length). $\endgroup$
    – Kuba
    Jun 21, 2016 at 11:13
  • $\begingroup$ Oh ok, I suppose it's my lack of understanding of the order in which Mathematica computes things which tripped me up. $\endgroup$
    – Tom
    Jun 21, 2016 at 11:15
14
$\begingroup$

There are so many ways to handle a problem like this and which one is preferred with depend on style, performance, the type and shape of your data, ease of recollection, etc., but here are several more:

Join[list, x ~Take~ Length[list] ~Partition~ 1, 2]

Riffle[Flatten @ list, x, {3, -1, 3}] ~Partition~ 3

PadRight[list, {Automatic, 3}, List /@ x]

And one inspired by J.M.'s use of Flatten

{list, x} ~Flatten~ {2} // Cases[{{x__}, y_} :> {x, y}]
$\endgroup$
2
  • 1
    $\begingroup$ Yes, that is making nice use of Riffle right there. Good when one can read the documentation. :) $\endgroup$
    – gwr
    Jun 21, 2016 at 11:25
  • $\begingroup$ @gwr Thank you! $\endgroup$
    – Mr.Wizard
    Jun 21, 2016 at 11:30
11
$\begingroup$

Shortest so far:

i = 1; list /. {a_, b_} :> {a, b, x[[i++]]}
$\endgroup$
1
  • 4
    $\begingroup$ +1, but after you add a Module to correctly localize i it will be longer than PadRight. :^) $\endgroup$
    – Mr.Wizard
    Jun 21, 2016 at 11:29
8
$\begingroup$
Transpose[Join[Transpose[list], {Take[x, Length[list]]}]]

should be quite fast for long lists. On my work desktop,

rand = RandomInteger[{1, 10}, {10^5, 2}];
xar = Array[x, 10^6];
AT = AbsoluteTiming;

AT[l1 = Transpose[Join[Transpose[rand], {Take[xar, Length[rand]]}]];]
(* {0.032721, Null} *)

AT[l2 = MapThread[Append, {rand, xar[[;; Length@rand]]}];]
(* {0.112556, Null} *)

AT[l3 = Table[{rand[[k, 1]], rand[[k, 2]], xar[[k]]}, {k, 1, 
     Length[rand]}];]
(* {1.975830, Null} *)

l1 == l2 == l3
(* True *)

EDIT: Some more timings just for fun, in no particular order :)

AT[l4 = (i = 1; rand /. {a_, b_} :> {a, b, xar[[i++]]});]
(* {0.161642, Null} *)

AT[l5 = ArrayFlatten[{{rand, {#} & /@ xar[[1 ;; Length[rand]]]}}];]
(* {0.186327, Null} *)

AT[l6 = Append @@@ 
    DeleteCases[Flatten[{rand, xar}, {{2}, {1}}], {_}];]
(* {1.054091, Null} *)

AT[l7 = MapIndexed[Join[#1, xar[[#2]]] &, rand];]
(* {0.277814, Null} *)

AT[l8 = Join[rand, xar~Take~Length[rand]~Partition~1, 2];]
(* {0.083558, Null} *)

AT[l9 = Riffle[Flatten@rand, xar, {3, -1, 3}]~Partition~3;]
(* {0.028951, Null} *)

AT[l10 = PadRight[rand, {Automatic, 3}, List /@ xar];]
(* {0.315211, Null} *)
$\endgroup$
6
$\begingroup$

How about this using Table?

Table[{list[[k, 1]], list[[k, 2]], x[[k]]}, {k, 1, Length[list]}]
$\endgroup$
5
$\begingroup$

Using MapIndexed...

MapIndexed[Join[#1, x[[#2]]] &, list]
$\endgroup$
4
$\begingroup$

Yet another possibility, using Flatten[] as a "generalized Transpose[]":

Append @@@ DeleteCases[Flatten[{list, x}, {{2}, {1}}], {_}]
   {{1, 2, x1}, {5, 2, x2}, {9, 3, x3}, {6, 5, x4}}
$\endgroup$
3
  • 1
    $\begingroup$ Shorter: Append @@@ Cases[Flatten[{list, x}, {2}], {_, _}] (and +1) $\endgroup$
    – Mr.Wizard
    Jun 21, 2016 at 14:38
  • $\begingroup$ Yes, that's more compact, @Mr. Wizard. Nevertheless, I still feel the need to remind myself of what Flatten[] is doing by specifying all levels explicitly in the second argument. But that's just my crutch... $\endgroup$ Jun 21, 2016 at 14:43
  • $\begingroup$ A perfectly valid crutch, IMHO. $\endgroup$
    – Mr.Wizard
    Jun 21, 2016 at 14:44
1
$\begingroup$
list = {{1, 2}, {5, 2}, {9, 3}, {6, 5}}; 
x = {x1, x2, x3, x4, x5, x6, x7};
ArrayFlatten[{{list, {#} & /@ x[[1 ;; 4]]}}]

{{1, 2, x1}, {5, 2, x2}, {9, 3, x3}, {6, 5, x4}}
$\endgroup$
1
$\begingroup$

I haven't seen this yet, but it may be degenerate with someone else's answer.

Append @@@ Partition[Riffle[list, x], 2]
$\endgroup$
1
$\begingroup$

ArrayFlatten[{{list, Transpose[{x[[;; Length@list]]}]}}]

See here for some interesting comparisons by Timo

$\endgroup$
0
$\begingroup$

I think the preferred way to append columns X to matrix A is probably:

Join[X, A, 2]

Adding a single column is slightly less tidy

Join[list, Transpose[{x}], 2]
$\endgroup$

Your Answer

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

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