11
$\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
  • 1
    $\begingroup$ closely related: 51407 $\endgroup$ Commented Jun 21, 2016 at 11:00
  • 1
    $\begingroup$ Also related: (189), (13748), (14494) $\endgroup$ Commented Jun 21, 2016 at 11:09

16 Answers 16

15
$\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$ Commented Jun 21, 2016 at 11:10
  • 1
    $\begingroup$ @Tom consider ;; list // Length and ;; (list // Length). $\endgroup$ Commented 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$ Commented Jun 21, 2016 at 11:15
16
$\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$ Commented Jun 21, 2016 at 11:25
  • $\begingroup$ @gwr Thank you! $\endgroup$ Commented Jun 21, 2016 at 11:30
12
$\begingroup$

Shortest so far:

i = 1; list /. {a_, b_} :> {a, b, x[[i++]]} 
$\endgroup$
1
  • 5
    $\begingroup$ +1, but after you add a Module to correctly localize i it will be longer than PadRight. :^) $\endgroup$ Commented Jun 21, 2016 at 11:29
11
$\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$
8
$\begingroup$

How about this using Table?

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

Using MapIndexed...

MapIndexed[Join[#1, x[[#2]]] &, list] 
$\endgroup$
6
$\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$ Commented Jun 21, 2016 at 14:38
  • 1
    $\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$ Commented Jun 21, 2016 at 14:43
  • $\begingroup$ A perfectly valid crutch, IMHO. $\endgroup$ Commented Jun 21, 2016 at 14:44
4
$\begingroup$

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}}*) 
$\endgroup$
4
$\begingroup$
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}} *) 
$\endgroup$
1
  • 1
    $\begingroup$ (+1) I like to see BlockMap in action. $\endgroup$ Commented Jan 4, 2024 at 19:59
3
$\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$
3
$\begingroup$

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

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

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

See here for some interesting comparisons by Timo

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

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

$\endgroup$
2
$\begingroup$
a = {{1, 2}, {5, 2}, {9, 3}, {6, 5}}; b = {x1, x2, x3, x4, x5, x6, x7}; 

A variant of 1066's first answer using SequenceCases

SequenceCases[Riffle[a, b[[;; Length @ a]]], x : {_, _} :> Flatten[x]] 

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

$\endgroup$

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.