質問内容
Python の sorted() の key 引数でソートする際に比較関数を指定できるようになっていますが、左辺、右辺両方を引数にとる比較関数を指定する方法はありますでしょうか。
C++ の場合、ソートする関数に以下のように左辺 (left-hand-side, lhs)、右辺 (right-hand-side, rhs) 両方を引数にとる比較関数を指定できますが、ソートする関数を自作する以外で Python でこれを実現する方法がわかりません。
cpp
1struct Point 2{ 3 double x; 4 double y; 5}; 6 7std::sort(points.begin(), points.end(), 8 [](const Point &lhs, const Point &rhs) -> bool 9{ 10 return lhs.y != rhs.y ? lhs.y > rhs.y : lhs.x > rhs.x; 11});
そのような事をしたい背景
右辺、左辺両方を引数にとる比較関数でないと、ソートできないケースが出てきたのが動機です。
sorted() の key 引数に関数を指定できますが、1つの引数をとる関数しか指定できないため、やりたいことが実現できないでいます。
ソート関数自体を実装すればいいと思いますが、標準ライブラリまたは numpy などの外部ライブラリの関数で可能であれば、やり方を教えていただきたいです。
python
1import matplotlib.pyplot as plt 2import numpy as np 3 4 5def draw_2d_points(points): 6 """2次元の点列を描画する。 7 """ 8 fig, ax = plt.subplots() 9 ax.grid() 10 ax.scatter(points[:, 0], points[:, 1]) 11 for i, p in enumerate(points): 12 ax.annotate(i, p, fontsize=14) 13 plt.plot() 14 15 16# 形状が (NumPoints, 2) である格子状の点列を作成する。 17X, Y = np.meshgrid(np.arange(10.0), np.arange(10.0), indexing="xy") 18points = np.column_stack([X.ravel(), Y.ravel()]) # [(N, M), (N, M)] -> (N*M, 2) 19 20# 点列に [-0.1, 0.1] の一様分布に従う乱数を加算する。 21points += np.random.uniform(-0.1, 0.1, points.shape) 22 23# シャッフルする。 24np.random.shuffle(points) 25draw_2d_points(points) # 図1 26 27# 単純に y > x 順でソートすると、加えたノイズの影響で左下から順番に並ばない。 28points = np.array(sorted(points, key=lambda p: (p[1], [0]))) 29draw_2d_points(points) # 図2 30 31# ソート関数自体を実装すれば実現できるが、それ以外に方法がないかという疑問 32def bubble_sort(arr, comp): 33 n = len(arr) 34 for i in range(n): 35 for j in range(0, n - i - 1): 36 if comp(arr[j], arr[j + 1]): 37 temp = arr[j].copy() # a, b = b, a 方式だと view がコピーされてしまうため 38 arr[j] = arr[j + 1] 39 arr[j + 1] = temp 40 41# 指定したい比較関数 42# y の差が 0.5 より大きい場合は y 座標で昇順、そうでない場合は x 座標で昇順ソートする。 43my_comp = lambda a, b: a[1] > b[1] if abs(a[1] - b[1]) > 0.5 else a[0] > b[0] 44 45bubble_sort(points, my_comp) 46draw_2d_points(points) # 図3
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/07/11 04:17