Numpy уникальный без сортировки

Как я могу использовать numpy unique без сортировки результата, но только в том порядке, в котором они появляются в последовательности? Что-то вроде этого?

a = [4,2,1,3,1,2,3,4]

np.unique(a) = [4,2,1,3]

а не

np.unique(a) = [1,2,3,4]

Использовать наивное решение должно быть хорошо, чтобы написать простую функцию. Но поскольку мне нужно делать это несколько раз, есть ли быстрый и аккуратный способ сделать это?

Ответ 1

Вы можете сделать это с помощью параметра return_index:

>>> import numpy as np
>>> a = [4,2,1,3,1,2,3,4]
>>> np.unique(a)
array([1, 2, 3, 4])
>>> indexes = np.unique(a, return_index=True)[1]
>>> [a[index] for index in sorted(indexes)]
[4, 2, 1, 3]

Ответ 2

Вы можете сделать это с помощью numpy, выполнив что-то вроде этого, mergsort стабилен, поэтому он позволит вам выбрать первое или последнее вхождение каждого значения:

def unique(array, orderby='first'):
    array = np.asarray(array)
    order = array.argsort(kind='mergesort')
    array = array[order]
    diff = array[1:] != array[:-1]
    if orderby == 'first':
        diff = np.concatenate([[True], diff])
    elif orderby == 'last':
        diff = np.concatenate([diff, [True]])
    else:
        raise ValueError
    uniq = array[diff]
    index = order[diff]
    return uniq[index.argsort()]

Этот ответ очень похож на:

def unique(array):
    uniq, index = np.unique(array, return_index=True)
    return uniq[index.argsort()]

Но numpy.unique использует нестабильный тип внутри, поэтому вам не гарантируется получение какого-либо определенного индекса, то есть первого или последнего.

Я думаю, что упорядоченный дикт мог бы также работать:

def unique(array):
    uniq = OrderedDict()
    for i in array:
         uniq[i] = 1
    return uniq.keys()