user21 and Teake Nutma already posted the two methods I use most often. Of these I recommend Part
as I believe it will be faster in general. Nevertheless these are hardly the only ways to accomplish this task. First, since the expression produced by List @@@ data
will not be packed Thread
may be faster than Transpose
:
Thread[List @@@ data]
One could also thread over Rule
, then replace the outer head with List
:
List @@ Thread[data, Rule]
From Undocumented form for Extract we could also use:
Rest @ Extract[data, {{0}, {All, 1}, {All, 2}}]
Benchmarks
A BenchmarkPlot
for all methods posted so far.
f1[a_] := a[[All, #]] & /@ {1, 2};
f2 = Transpose[# /. (a_ -> b_) :> {a, b}] &;
f3 = Transpose[List @@@ #] &;
f4 = Thread[List @@@ #] &;
f5 = List @@ Thread[#, Rule] &;
f6 = Rest@Extract[#, {{0}, {All, 1}, {All, 2}}] &;
f7 = Query[{Keys, Values}];
f8 = {Keys@#, Values@#} &
Needs["GeneralUtilities`"]
g[n_] := Rule @@@ RandomInteger[9, {n, 2}];
BenchmarkPlot[{f1, f2, f3, f4, f5, f6, f7, f8}, g, 2^Range[5, 20], "IncludeFits" -> True]
(click for larger)
Once again Query
has some crazy overhead and should be avoided when performance matters unless inputs are very large.
Keys
and Values
are very fast when used apart from Query
.
List @@ Thread[data, Rule]
is as fast as Keys
and Values
, and faster than Part
and Extract
which I did not expect.
As expected Thread
is slightly faster than Transpose
with unpacked data. (f3
and f4
)
{list1, list2} = {data[[All, 1]], data[[All, 2]]}
$\endgroup$