Если я правильно понимаю ваш код, то порядок, который вы имеете в виду, является стандартным, только то, что он начинается с 0
, охватывает +/-infinity
и достигает максимума -0
. Кроме того, у нас есть простой лексикографический порядок слева направо.
Теперь, если ваш массив dtype является целым числом, обратите внимание на следующее: Из-за представления представления отрицательных значений приведение типов к unsigned int делает ваш заказ стандартным. Вдобавок к этому, если мы используем кодирование с прямым порядком байтов, эффективное лексикографическое упорядочение может быть достигнуто путем приведения к виду void
dtype.
Приведенный ниже код показывает, что на примере 10000x4x4
этот метод дает тот же результат, что и ваш код Python.
Он также тестирует его на примере 7,900,000x4x4
(используя массив, а не dict). На моем скромном ноутбуке этот метод занимает 8
секунд.
import numpy as np
def compare(x, y):
# print('DD '+str(x[0]))
if(np.array_equal(x[1],y[1])==True):
return -1
a = x[1].flatten()
b = y[1].flatten()
idx = np.where( (a>b) != (a<b) )[0][0]
if a[idx]<0 and b[idx]>=0:
return 0
elif b[idx]<0 and a[idx]>=0:
return 1
elif a[idx]<0 and b[idx]<0:
if a[idx]>b[idx]:
return 0
elif a[idx]<b[idx]:
return 1
elif a[idx]<b[idx]:
return 1
else:
return 0
def cmp_to_key(mycmp):
class K:
def __init__(self, obj, *args):
self.obj = obj
def __lt__(self, other):
return mycmp(self.obj, other.obj)
return K
def custom_sort(a):
assert a.dtype==np.int64
b = a.astype('>i8', copy=False)
return b.view(f'V{a.dtype.itemsize * a.shape[1]}').ravel().argsort()
tblocks = np.random.randint(-9,10, (10000, 4, 4))
tblocks = dict(enumerate(tblocks))
tblocks_s = sorted(tblocks.items(),key=cmp_to_key(compare))
tblocksa = np.array(list(tblocks.values()))
tblocksa = tblocksa.reshape(tblocksa.shape[0], -1)
order = custom_sort(tblocksa)
tblocks_s2 = list(tblocks.items())
tblocks_s2 = [tblocks_s2[o] for o in order]
print(tblocks_s == tblocks_s2)
from timeit import timeit
data = np.random.randint(-9_999, 10_000, (7_900_000, 4, 4))
print(timeit(lambda: data[custom_sort(data.reshape(data.shape[0], -1))],
number=5) / 5)
Пример вывода:
True
7.8328493310138585