Перейти к основному содержимому

20.10. Как отсортировать данные?

В: Как отсортировать данные? Например, список персонажей по алфавиту, или набор чисел от меньшего к большему.

О: Прежде всего такие данные должны лежать в одном массиве. Например:

$personage[0]='Петя'
$personage[1]='Ваня'
$personage[2]='Сева'
$personage[3]='Саша'
$personage[4]='Лёня'

Или:

number[0]=345
number[1]=798
number[2]=930
number[3]=121
number[4]=474

Далее можно воспользоваться простым алгоритмом:

! объявляем локальные переменные

local $varMax, index, $personage_temp
! копируем данные во временный массив,

! чтоб не затереть исходный

copyarr '$personage_temp','$personage'
! с помощью цикла выбираем элементы по одному

! из временного массива, имеющие минимальное значение

loop while arrsize('$personage_temp')>0:
! цикл будет работать, пока размер временного массива

! больше нуля

! получаем минимальное значение

$varMax=$min('$personage_temp')
! определяем, в каком элементе лежит это значение

index=arrpos('$personage_temp',$varMax)
! выводим на экран

*pl $varMax
! или запоминаем в другом массиве

$personage_sort[]=$varMax
! удаляем элемент из временного массива

killvar '$personage_temp',index
end

Обратите внимание, при работе с текстовыми значениями меньшим считается то, которое идёт раньше согласно алфавитного порядка.

Сортировка чисел ничем практически не отличается:

local varMax, index, number_temp
copyarr 'number_temp','number'
loop while arrsize('number_temp')>0:
varMax=max('number_temp')
index=arrpos('number_temp',varMax)
*pl varMax
number_sort[]=varMax
killvar 'number_temp',index
end

Этот алгоритм достаточно быстр и прост для решения большинства задач. Он требует нескольких переменных и дополнительный массив для временного хранения данных. Если необходимо отсортировать данные сразу внутри массива, не прибегая к помощи дополнительного массива, можно воспользоваться методом сортировки "пузырьком":

проходы=0
loop local проходы=0 while проходы<arrsize("сортируемый_массив") step проходы+=1:
loop local всплытия=проходы while всплытия<arrsize("сортируемый_массив") step всплытия+=1:
if сортируемый_массив[проходы] < сортируемый_массив[всплытия]:
! или, если нужен другой порядок:

!if сортируемый_массив[проходы] > сортируемый_массив[всплытия]:

запоминальная_переменная = сортируемый_массив[проходы]
сортируемый_массив[проходы] = сортируемый_массив[всплытия]
сортируемый_массив[всплытия] = запоминальная_переменная
end
end
end

Операции сравнения прекрасно работают с текстовыми значениями по тому же принципу, что и функции $max и $min.

Готовое решение по методу сортировки пузырьком есть в библиотеке "easy.math" с различными дополнительными возможностями. Смотрите функцию em.arr.sort.