Московский физико-технический институт
Опубликован: 23.12.2005 | Доступ: свободный | Студентов: 2869 / 253 | Оценка: 4.61 / 4.44 | Длительность: 27:18:00
ISBN: 978-5-9556-0051-2
Лекция 4:

Контейнеры

Сортировка

Алгоритмы сортировки - это одна из тех вещей, которые изучают все программисты, и которыми затем практически никогда не пользуются (потому что все современные библиотеки функций и классов предоставляют готовые реализации сортировки ). Предоставляет свою реализацию сортировки и Флэш МХ. Посмотрим, хороша ли она, и если да, то чем.

Сортировка чисел в массиве

Попробуем отсортировать числовой массив.

a_array = [3, 0.5, +3, -3, 1e12, 1e-12, 12, 112];
a_array.sort();
trace(a_array);

На выходе получаем:

-3,0.5,1000000000000,112,12,1e-12,3,3

Видно, что метод sort() (в отличие от многих методов массива, с которыми мы познакомимся позднее) действительно изменяет массив. Но что это? В каком порядке он расставил числа? Мы наткнулись на неприятную особенность этого метода: по умолчанию он преобразует все элементы массива в строки и лишь потом пытается отсортировать. Чтобы получить правильно отсортированный массив чисел, нам придется написать что-то вроде

a_array.sort(function(a,b){return a-b;});

Тогда на выходе действительно будет

-3,1e-12,0.5,3,3,12,112,1000000000000

О том, что на самом деле означает строчка a_array.sort(function(a,b){return a-b;});, вы узнаете чуть позднее. Впрочем, уже ясно, что для сортировки по убыванию надо написать a_array.sort(function(a,b){return b-a;});. Также приятное известие состоит в том, что в ActionScript 2 рассматриваемая проблема решена - в метод sort можно передавать набор управляющих флагов, один из которых (Array.NUMERIC) командует трактовать содержимое массива как числа.

Сортировка строк

Но зато с сортировкой строк проблем у нас не будет. Пишем, например:

s_array = ["bulb", "bulb.", "c", "CC", "ground"];
s_array.sort();
trace(s_array);

и получаем в результате

CC,bulb,bulb.,c,ground

А как нам отсортировать массив в обратном направлении (по убыванию)? В ActionScript 2 можно передать флаг Array.DESCENDING. Нам же придется сделать a_array.reverse();

Сортировка объектов по полю

Если в массиве лежат объекты, то их можно отсортировать по значению любого из полей. Конечно, чтобы такая операция имела смысл, указанное поле должно присутствовать практически во всех сортируемых объектах. Но, как это водится во Флэш МХ, сообщений об ошибках мы не получим, даже если этого поля нет ни в одном из объектов. Как бы то ни было, вот пример такой сортировки (выполняющейся с помощью специального метода Array.sortOn ):

a_array = [{name:"aa", info:112}, {name:"bb", info: 23},
   {name: "ba", info:1e-5}];
a_array.sortOn("name");
for (var i=0; i<a_array.length; i++){
   trace("{" + a_array[i].name + ", " + a_array[i].info + "}");
}
trace("---------");
a_array.sortOn("info");
for (var i=0; i<a_array.length; i++){
   trace("{" + a_array[i].name + ", " + a_array[i].info + "}");
}

На выходе получим:

{aa, 112}
{ba, 0.00001}
{bb, 23}
---------
{ba, 0.00001}
{aa, 112}
{bb, 23}

Видим, что непорядок с сортировкой чисел имеет место и здесь. Правда, исправить его будет чуть сложнее, чем при сортировке обычных чисел, а не объектов. Ведь функция sortOn не имеет дополнительных параметров - в нее нельзя передать функцию сортировки. Разбираться с этой неприятностью мы будем уже в следующем подпараграфе. А пока заметим, что если у какого-то из объектов поля name (или info при сортировке по info ) не будет, он попадет в начало массива, поскольку при обращении к этому полю будет возвращаться undefined. В свою очередь, при преобразовании undefined в строчку, получится пустая строка, которая "меньше" любой другой строки. То же самое случится, если в массиве попадется, например, обыкновенное число вместо объекта. Главное, чтобы вместо объекта в массиве не стояла строка. По неизвестным причинам Флэш падает при попытке запустить сортировку такого массива в интегрированном в среду плеере. (Хотя во внешнем плеере ничего страшного не происходит; так что можно обойтись без специальных проверок на этот счет.)