2016-03-30 3 views
2

Я пытаюсь в течение нескольких дней исправить это, но я просто не могу с этим справиться.python: Сортировка списка списков по диапазону элементов

У меня есть список списков, где каждый список состоит из значений от 0 до 5:

[[ 0. 0. 4. 2. 2. 2. 2. 2. 2. 2.] 
[ 0. 0. 1. 2. 3. 3. 3. 3. 3. 3.] 
[ 0. 0. 2. 3. 4. 4. 1. 2. 1. 2.] 
[ 0. 0. 3. 4. 5. 1. 4. 4. 5. 5.] 
... 
[ 0. 0. 5. 3. 3. 3. 4. 3. 4. 3.] 
[ 0. 0. 3. 4. 1. 1. 1. 1. 4. 4.] 
[ 0. 0. 3. 4. 1. 3. 3. 3. 3. 1.] 
[ 0. 0. 1. 4. 4. 5. 3. 4. 3. 1.]] 

Теперь я хотел бы отсортировать этот список, начиная с самим последним элементом, то вторыми последними и т.д. вплоть до самого начала, чтобы получить что-то вроде:

[[ 0. 0. 3. 4. 1. 3. 3. 3. 3. 1.] 
[ 0. 0. 1. 4. 4. 5. 3. 4. 3. 1.] 
[ 0. 0. 5. 3. 3. 3. 3. 3. 4. 1.] 
[ 0. 0. 2. 3. 4. 4. 1. 2. 1. 2.] 
... 
[ 0. 0. 3. 4. 1. 1. 1. 1. 4. 4.] 
[ 0. 0. 3. 3. 3. 4. 4. 4. 4. 4.] 
[ 0. 0. 4. 4. 3. 4. 5. 5. 1. 5.] 
[ 0. 0. 3. 4. 5. 1. 4. 4. 5. 5.]] 

всех ответов на сортировку массивов/список вопросов, которые я нашел в Интернете, рассматриваемые с различными столбцами/элементами, в то время как я не мог получить этот набор элементов для работы , В итоге единственным решением, которое сработало, было:

array = array[np.lexsort((array[:,-9], array[:,-8], array[:,-7], array[:,-6], array[:,-5], array[:,-4], array[:,-3], array[:,-2], array[:,-1]))] 

Это не только очень уродливое, но и не очень гибкое. Любая попытка заменить эту команду циклом или переменной не удалась.

Любые предложения были бы очень оценены!

ответ

2

Вы можете просто транспонировать массив ввода, а затем использовать np.lexsort, чтобы получить сортировки индексов для векторизованного и, таким образом, довольно эффективное решение, как так -

array[np.lexsort(array[:,1:].T)] 

Пример запуска -

In [128]: # Random array of integers 
    ...: array = np.random.randint(0,9,(5,10)) 
    ...: 
    ...: # Original method 
    ...: A = ((array[:,-9], array[:,-8], array[:,-7], array[:,-6], array[:,-5], \ 
    ...:  array[:,-4], array[:,-3], array[:,-2], array[:,-1])) 
    ...: out_loopy = array[np.lexsort(A)] 
    ...: 
    ...: # Vectorized method 
    ...: out_vectorized = array[np.lexsort(array[:,1:].T)] 
    ...: 

In [129]: np.allclose(out_loopy,out_vectorized) 
Out[129]: True 
+1

ЭТО - правильный способ сделать это. Ухабистая версия 'sorted (LoL, key = lambda l: l [:: - 1])'. благодаря – dawg

2

Дано:

LoL=[[ 0., 0., 4., 2., 2., 2., 2., 2., 2., 2.,], 
[ 0., 0., 1., 2., 3., 3., 3., 3., 3., 3.,], 
[ 0., 0., 2., 3., 4., 4., 1., 2., 1., 2.,], 
[ 0., 0., 3., 4., 5., 1., 4., 4., 5., 5.,], 
[ 0., 0., 5., 3., 3., 3., 4., 3., 4., 3.,], 
[ 0., 0., 3., 4., 1., 1., 1., 1., 4., 4.,], 
[ 0., 0., 3., 4., 1., 3., 3., 3., 3., 1.,], 
[ 0., 0., 1., 4., 4., 5., 3., 4., 3., 1.,]] 

Используйте ключевую функцию:

>>> sorted(LoL, key=lambda l: l[::-1]) 
[[0.0, 0.0, 3.0, 4.0, 1.0, 3.0, 3.0, 3.0, 3.0, 1.0], 
[0.0, 0.0, 1.0, 4.0, 4.0, 5.0, 3.0, 4.0, 3.0, 1.0], 
[0.0, 0.0, 2.0, 3.0, 4.0, 4.0, 1.0, 2.0, 1.0, 2.0], 
[0.0, 0.0, 4.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0, 2.0], 
[0.0, 0.0, 1.0, 2.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0], 
[0.0, 0.0, 5.0, 3.0, 3.0, 3.0, 4.0, 3.0, 4.0, 3.0], 
[0.0, 0.0, 3.0, 4.0, 1.0, 1.0, 1.0, 1.0, 4.0, 4.0], 
[0.0, 0.0, 3.0, 4.0, 5.0, 1.0, 4.0, 4.0, 5.0, 5.0]] 

Если те Numpy массивы, использовать ndarray.sort:

>>> m=np.matrix(LoL) 
>>> m 
array([[ 0., 0., 4., 2., 2., 2., 2., 2., 2., 2.], 
     [ 0., 0., 1., 2., 3., 3., 3., 3., 3., 3.], 
     [ 0., 0., 2., 3., 4., 4., 1., 2., 1., 2.], 
     [ 0., 0., 3., 4., 5., 1., 4., 4., 5., 5.], 
     [ 0., 0., 5., 3., 3., 3., 4., 3., 4., 3.], 
     [ 0., 0., 3., 4., 1., 1., 1., 1., 4., 4.], 
     [ 0., 0., 3., 4., 1., 3., 3., 3., 3., 1.], 
     [ 0., 0., 1., 4., 4., 5., 3., 4., 3., 1.]]) 
>>> m[m[:,-1].argsort()] 
array([[ 0., 0., 3., 4., 1., 3., 3., 3., 3., 1.], 
     [ 0., 0., 1., 4., 4., 5., 3., 4., 3., 1.], 
     [ 0., 0., 4., 2., 2., 2., 2., 2., 2., 2.], 
     [ 0., 0., 2., 3., 4., 4., 1., 2., 1., 2.], 
     [ 0., 0., 1., 2., 3., 3., 3., 3., 3., 3.], 
     [ 0., 0., 5., 3., 3., 3., 4., 3., 4., 3.], 
     [ 0., 0., 3., 4., 1., 1., 1., 1., 4., 4.], 
     [ 0., 0., 3., 4., 5., 1., 4., 4., 5., 5.]]) 
+0

Я получаю следующее сообщение об ошибке: ValueError: значение истинности массива с более чем одним элементом неоднозначно. Используйте a.any() или a.all(). Если я затем добавить .any() или .all() я получаю: TypeError: объект «» numpy.bool_ не итерацию –

+0

см редактирования для нп версии – dawg

+0

Попробуйте обновление ... – dawg

0

Используйте следующую функцию

сортировки
def mysort(list1,list2): 
    i = min(len(list1),len(list2))-1 # in case unequal lines 
    while (i>0) and list1[i]== list2[i]: 
    i -= 1 
    return cmp(list1[i],list2[i]) 

Протестировано (печатает правильный ответ)

LL = [[ 0, 0, 4, 2, 2, 2, 2, 2, 2, 2,], 
[ 0, 0, 1, 2, 3, 3, 3, 3, 3, 3,], 
[ 0, 0, 2, 3, 4, 4, 1, 2, 1, 2,], 
[ 0, 0, 3, 4, 5, 1, 4, 4, 5, 5,], 
[ 0, 0, 5, 3, 3, 3, 4, 3, 4, 3,], 
[ 0, 0, 3, 4, 1, 1, 1, 1, 4, 4,], 
[ 0, 0, 3, 4, 1, 3, 3, 3, 3, 1,], 
[ 0, 0, 1, 4, 4, 5, 3, 4, 3, 1,]] 

LL.sort(mysort) 
print (LL) 
+0

Вы можете использовать 'i = 9', если вы действительно уверены, что все подкатегории имеют длину 10. Но это делает код более надежным и универсальным. –

Смежные вопросы