11

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)
Tom
  • 3,416
  • 1
  • 18
  • 33

15 Answers15

16

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}]
Mr.Wizard
  • 271,378
  • 34
  • 587
  • 1,371
15

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

e.doroskevic
  • 5,959
  • 1
  • 13
  • 32
  • 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? – Tom Jun 21 '16 at 11:10
  • 1
    @Tom consider ;; list // Length and ;; (list // Length). – Kuba Jun 21 '16 at 11:13
  • Oh ok, I suppose it's my lack of understanding of the order in which Mathematica computes things which tripped me up. – Tom Jun 21 '16 at 11:15
12

Shortest so far:

i = 1; list /. {a_, b_} :> {a, b, x[[i++]]}
xzczd
  • 65,995
  • 9
  • 163
  • 468
10
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} *)
Marius Ladegård Meyer
  • 6,805
  • 1
  • 17
  • 26
8

How about this using Table?

Table[{list[[k, 1]], list[[k, 2]], x[[k]]}, {k, 1, Length[list]}]
Lotus
  • 2,671
  • 11
  • 10
7

Using MapIndexed...

MapIndexed[Join[#1, x[[#2]]] &, list]
Ymareth
  • 4,741
  • 20
  • 28
6

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}}
J. M.'s missing motivation
  • 124,525
  • 11
  • 401
  • 574
3
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}}
3

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

Append @@@ Partition[Riffle[list, x], 2]
N.J.Evans
  • 5,093
  • 19
  • 25
3

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

See here for some interesting comparisons by Timo

user41753
  • 31
  • 1
3

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]
mikado
  • 16,741
  • 2
  • 20
  • 54
3
a = {{1, 2}, {5, 2}, {9, 3}, {6, 5}};
b = {x1, x2, x3, x4, x5, x6, x7};

Some more possibilities:

ReplacePart

ReplacePart[i_ :> Append[a[[i]], b[[i]]]] @ a

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

Table with Splice (new in 12.1)

Table[{Splice @ a[[i]], b[[i]]}, {i, Length @ a}]

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

Transpose with TrimRight

Needs["GeneralUtilities`"]

Flatten /@ Transpose @ TrimRight[{a, b}]

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

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

Using Transpose and ReplaceAll as follows:

Transpose@{a, b[[;; Length@a]]} /. x_ /; VectorQ[x] :> Splice@x

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

Or using Cases:

Cases[Transpose@{#, b[[;; Length@#]]}, {x : {__}, y_} :> {Splice@x, y}] &@a

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

E. Chan-López
  • 23,117
  • 3
  • 21
  • 44
3
Clear["Global`*"]
list = {{1, 2}, {5, 2}, {9, 3}, {6, 5}};
x = {x1, x2, x3, x4, x5, x6, x7};

To accomodate varying lengths of each of the above vectors:

minlen = Min[Length /@ {list, x}];
listm = list[[1 ;; minlen]];
xm = x[[1 ;; minlen]];

Here are some variations without repeating the Part construct:

SequenceReplace[
 Riffle[listm, xm], {a_List, b_ } :> {Sequence @@ a, b}]

MapThread[Riffle[#1, #2, 1 + Length@#1] &, {listm, xm}]

Join[listm, Transpose[{xm}], 2]

MapThread[Join[#1, {#2}] &, {listm, xm}]

MapThread[Append[#1, #2] &, {listm, xm}]

MapThread[Catenate[{#1, #2}] &, {listm, Transpose[{xm}]}]


Result:

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

Syed
  • 52,495
  • 4
  • 30
  • 85
3
BlockMap[Flatten,Riffle[list, x[[;;Length@list]]],2]

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

In addition, a variation on the neat answer given by xzczd

MapThread[Replace,{list,{a_, b_} :> {a, b, x[[#]]}&/@Range@Length@list}]

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

user1066
  • 17,923
  • 3
  • 31
  • 49