1
$\begingroup$

This question already has an answer here:

I wonder how I can turn the list $\{a_1,...,a_n\}$ into the new list $\{(a_1,1),...,(a_n,n)\}$, i.e $a_k \mapsto (a_k,k)$, how do I do that?

I figured the function Tuples might work, but it just lists all tuples $(a_i,j)$, $i,j \in [n]$. Can't seem to find any other function that accomplishes what I want. Thanks.

$\endgroup$

marked as duplicate by Mr.Wizard Feb 9 '15 at 6:11

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • $\begingroup$ Related: (3585); this is essentially a simpler version of that question. $\endgroup$ – Mr.Wizard Feb 9 '15 at 6:03
  • $\begingroup$ I found a closer one. Closing. $\endgroup$ – Mr.Wizard Feb 9 '15 at 6:11
1
$\begingroup$
n = 5;

list = Array[a, n];

Thread[{list, Range[Length[list]]}]

{{a[1], 1}, {a[2], 2}, {a[3], 3}, {a[4], 4}, {a[5], 5}}

EDIT (addressing additional question in OP comment): If m and n are known:

m = 10; n = 6;

list = Array[a, n];

Thread[{list, Range[m - n + 1, m]}]

{{a[1], 5}, {a[2], 6}, {a[3], 7}, {a[4], 8}, {a[5], 9}, {a[6], 10}}

$\endgroup$
  • $\begingroup$ Thanks! Now, what if the second list is not $\{1,...n\}$ but $\{m-(n-1),m-(n-2),...,m\}$, $m>n$? $\endgroup$ – Erik Vesterlund Feb 8 '15 at 22:02
4
$\begingroup$

I've often wondered what the best approach is for this. I find myself combining two lists a and b of the same length in this way quite frequently. I have always used Transpose[{a,b}], but wondered if that was the most efficient way to do it. It seems like it would require moving around a lot of stuff in memory.

So I tested the speed of the solutions shown here, as well as checked whether they preserved packed arrays.

Needs["Developer`"]
a=RandomInteger[1000000000,1000000];
b=Range[1000000];
PackedArrayQ@a
True
PackedArrayQ@b
True
Timing[c=Thread[{a,b}];]
PackedArrayQ@c
{0.278477,Null}
False
Timing[c=Transpose[{a,b}];]
PackedArrayQ@c
{0.011906,Null}
True
Timing[c=MapIndexed[{#1,First@#2}&,a];]
PackedArrayQ@c
{1.256647,Null}
False
Timing[c=MapThread[List,{a,b}];]
PackedArrayQ@c
{0.371252,Null}
False
Timing[c=Inner[List,a,b,List];]
PackedArrayQ@c
{0.274188,Null}
False

I had high hopes for Thread. However Transpose is the clear winner, and the only one that preserves packed arrays.

Any other solutions we should try?

$\endgroup$
3
$\begingroup$

The most efficient way should be this (because of Transpose):

n = 10;
list = Array[a, n]
Transpose[{ list, Range @ Length[list]}]
{a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10]}
 {{a[1], 1}, {a[2], 2}, {a[3], 3}, {a[4], 4}, {a[5], 5}, 
  {a[6], 6}, {a[7], 7}, {a[8], 8}, {a[9], 9}, {a[10], 10}}

For certain similar functionality look e.g. at Tally, BinLists, BinCounts.

$\endgroup$
2
$\begingroup$

Here is another option:

n=5;
list=RandomInteger[10,n];
MapIndexed[{#1,First@#2}&,list]

{{10,1},{4,2},{8,3},{2,4},{1,5}}

$\endgroup$
  • $\begingroup$ We came on with the same solution nearly at the same time :-) $\endgroup$ – mgamer Feb 8 '15 at 22:02
  • $\begingroup$ @mgamer ... technically it's mine by 3 minutes.. :) $\endgroup$ – Murta Feb 8 '15 at 22:03
  • $\begingroup$ Your are absolutely right! :-) $\endgroup$ – mgamer Feb 8 '15 at 22:06
1
$\begingroup$

There are a lot of ways to accomplish this, one of them is also MapIndexed:

list = RandomInteger[{1, 20}, 10]

and then

MapIndexed[{#1, First @ #2} &, list]
$\endgroup$
  • 1
    $\begingroup$ This is the same answer I posted.. $\endgroup$ – Murta Feb 8 '15 at 22:02
  • 1
    $\begingroup$ Yes, I just saw it - browser updates in intervals, so I did not see your answer... I was typing in the same moment funny $\endgroup$ – mgamer Feb 8 '15 at 22:04
0
$\begingroup$

This will do what you want:

Module[{i = 1},
 {#, i++} & /@ RandomReal[{-1, 1}, 10]
]

You need to localise the i iterator so that it works on multiple occasions. If you didn't do this, the second column would start at whatever the length of the previous list was.

It should be noted that this method performs similarly to, but a bit more slowly than, the MapIndexed solution proposed by others.

list = RandomReal[{-1, 1}, 1000000];

Module[{i = 1}, {#, i++} & /@ list]; // Timing

(*{0.967206, Null}*)

MapIndexed[{#1, First@#2} &, list]; // Timing

(*{0.904806, Null} *)
$\endgroup$

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