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$

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$
  • $\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 '16 at 11:10
  • 1
    $\begingroup$ @Tom consider ;; list // Length and ;; (list // Length). $\endgroup$ – Kuba Jun 21 '16 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 '16 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$
  • 1
    $\begingroup$ Yes, that is making nice use of Riffle right there. Good when one can read the documentation. :) $\endgroup$ – gwr Jun 21 '16 at 11:25
  • $\begingroup$ @gwr Thank you! $\endgroup$ – Mr.Wizard Jun 21 '16 at 11:30
10
$\begingroup$

Shortest so far:

i = 1; list /. {a_, b_} :> {a, b, x[[i++]]}
$\endgroup$
  • 4
    $\begingroup$ +1, but after you add a Module to correctly localize i it will be longer than PadRight. :^) $\endgroup$ – Mr.Wizard Jun 21 '16 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$
  • 1
    $\begingroup$ Shorter: Append @@@ Cases[Flatten[{list, x}, {2}], {_, _}] (and +1) $\endgroup$ – Mr.Wizard Jun 21 '16 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$ – J. M. is away Jun 21 '16 at 14:43
  • $\begingroup$ A perfectly valid crutch, IMHO. $\endgroup$ – Mr.Wizard Jun 21 '16 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, privacy policy and cookie policy

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