7

x と y の 2 つのリストがあり、x ソートの順列で x を並べ替え、y を並べ替えたいと考えています。たとえば、与えられた

x = [4, 2, 1, 3]
y = [40, 200, 1, 30]

私は手に入れたい

x_sorted = [1,2,3,4]
y_sorted = [1, 200, 30, 40]

過去の質問で説明したように、これを解決する簡単な方法は

x_sorted, y_sorted = zip(*sorted(zip(x,y)))

これが私の質問です。これを行う最も速い方法は何ですか?


タスクを実行するには3つの方法があります。

import numpy as np
x = np.random.random(1000)
y = np.random.random(1000)

方法 1:

x_sorted, y_sorted = zip(*sorted(zip(x,y))) #1.08 ms 

方法 2:

foo = zip(x,y)
foo.sort()
zip(*foo)       #1.05 ms

方法 3;

ind = range(1000)
ind.sort(key=lambda i:x[i])
x_sorted = [x[i] for i in ind]
y_sorted = [y[i] for i in ind]  #934us

上記の 3 つの方法よりも高速に実行されるより良い方法はありますか?


追加の質問。

  1. 方法2はソート方法を使っているのに方法1よりも速くないのはなぜですか?
  2. 方法 2 を個別に実行すると、高速になります。IPython ターミナルで、

私は持っている

%timeit foo = zip(x,y)   #1000 loops, best of 3: 220 us per loop
%timeit foo.sort()       #10000 loops, best of 3: 78.9 us per loop
%timeit zip(*foo)        #10000 loops, best of 3: 73.8 us per loop
4

3 に答える 3

4
>>> x = [4, 2, 1, 3]
>>> y = [40, 200, 1, 30]    
>>> x_sorted, y_sorted = zip(*sorted(zip(x, y), key=lambda a:a[0]))
>>> x_sorted
(1, 2, 3, 4)
>>> y_sorted
(1, 200, 30, 40)

Performance:

>>> timeit('foo = zip(x,y); foo.sort(); zip(*foo)', 'from __main__ import x, y', number=1000)
1.0197240443760691
>>> timeit('zip(*sorted(zip(x,y)))', 'from __main__ import x, y', number=1000)
1.0106219310922597
>>> timeit('ind = range(1000); ind.sort(key=lambda i:x[i]); x_sorted = [x[i] for i in ind]; y_sorteds = [y[i] for i in ind]', 'from __main__ import x, y', number=1000)
0.9043525504607857
>>> timeit('zip(*sorted(zip(x, y), key=lambda a:a[0]))', 'from __main__ import x, y', number=1000)
0.8288150863453723

To see the full picture:

>>> timeit('sorted(x)', 'from __main__ import x, y', number=1000)
0.40415491505723367            # just getting sorted list from x
>>> timeit('x.sort()', 'from __main__ import x, y', number=1000)
0.008009909448446706           # sort x inplace

@falsetru method - fastest for np.arrays

>>> timeit('order = np.argsort(x); x_sorted = x[order]; y_sorted = y[order]', 'from __main__ import x, y, np', number=1000)
0.05441799872323827

As @AshwiniChaudhary suggested in comments, for lists there's a way to speed it up by using itertools.izip instead of zip:

>>> timeit('zip(*sorted(izip(x, y), key=itemgetter(0)))', 'from __main__ import x, y;from operator import itemgetter;from itertools import izip', number=1000)
0.4265049757161705
于 2013-08-21T04:49:40.083 に答える