Просмотр полной версии : Как отсортировать Vector
HardCoder
23.02.2012, 22:23
Здравствуйте. Мне нужно отсортировать, например, вектор Vector.<SomeObject> по полю prop:uint каждого элемента. То есть проверить каждый элемент вектора и узнать его prop (чем выше prop - тем выше индекс элемента). В справке нет ни одного примера как это сделать. В гугле тоже нет (только информация как сортировать вектор не стандартным sort()). Нашел простой код:public function initTurn():void {
var test:Vector.<int> = new <int>[3,5,2,3,9,0,1,8];
test.sort(compare);
for (var i:uint = 0; i < test.length; i++) {
trace(test[i]);
}
// выводит 0,1,2,3,3,5,8,9
}
private function compare(x:int, y:int):Number {
if (x > y) {
return 1;
} else if (x < y) {
return -1;
} else {
return 0;
}
}Захотел в нем разобраться и переделать под свой случай. Но, как говорится: "смотрю в книгу - вижу фигу". Что это за x и y, откуда они берутся, почему при вызове test.sort(compare) - не передаются никакие параметры, кто получает Number, возвращаемый функцией compare, и что оно с ним делает?
Пожалуйста, подскажите код для сортировки вектора с пользовательским типом (не int, Number, uint). Или, хотя бы, подскажите что за колдовство происходит при вызове этой строчки: test.sort(compare);, может дальше как-нибудь сам разберусь.
общий смысл вкратце:
var elements:Vector.<int> = new <int>[3,5,2,3,9,0,1,8];
private function compare(element1:int, element2:int):int {
if (element1 > element2)
return 1;
if (element1 < element2)
return -1;
return 0;
}
Причем тут массив? Метод сортировки у Vector свой.
Описание параметров, которые он принимает:
Параметры
compareFunction:Function — Метод сравнения, определяющий поведение при сортировке.
Указанный метод должен взять два аргумента базового типа (T) вектора и возвратить число:
function compare(x:T, y:T):Number {}
Логика функции compareFunction такова, что при наличии двух элементов x и y функция возвращает одно из следующих трех значений:
отрицательное число, если x стоит перед y после сортировки;
0, если x равно y;
положительное число, если элемент x должен следовать за y в отсортированной последовательности.
HardCoder
23.02.2012, 22:35
СлаваRa, спасибо, теперь понял: x и y - это просто перебираемые элементы вектора :). В таком случае вот как надо:var test:Vector.<SomeObject> = new <SomeObject>[obj1, obj2, obj3];
test.sort(compare);
private function compare(element1:SomeObject, element2:SomeObject):Number {
if (element1.prop > element2.prop ) {
return 1;
} else if (element1.prop < element2.prop) {
return -1;
} else {
return 0;
}
}
HardCoder
23.02.2012, 22:41
Вот я не хороший человек!!! Только сейчас увидел про функцию сравнения в справке :). Читал когда-то давно и то ли не понял, то ли не дочитал. А сейчас - вместо того чтобы еще раз посмотреть - начал искать черную кошку в темной комнате, которой в этой комнате нет...
Что смешно, так это то, что этот пример - бездумная копия из мануала, на самом деле не нужно возвращать строго -1, 0 или 1, достаточно просто возвращать положительное, отрицательное и 0. Т.е. функция сортировки может выглядеть так:
private function sortHelper(x:int, y:int):int
{
return x - y;
}
Да, с поправкой на то, что если вы предвидите ситуацию, когда будет переполнение, например, если отнять 1 от int.MIN_VALUE, то, возможно, есть смысл нормализовать значения, например так:
1 / (1 / y - 1 / x)
Но если такие случаи не предвидятся, то это будет лишним.
на самом деле не нужно возвращать строго -1, 0 или 1, достаточно просто возвращать положительное, отрицательное и 0.
А это советую перепроверить. Помню, был как-то очень удивлён, что сортировка работала неправильно — оказалось надо именно -1, 0, 1, хотя в документации было сказано про положительные и отрицательные в общем.
Я проверил - у меня работает :)
В конце концов, если так уж прям замуж невтерпеж, то
private function sortHelper(x:int, y:int):int
{
var result:int = x - y;
return Math.abs(result) / result;
}
Dima_DPE
24.02.2012, 14:00
В конце концов, если так уж прям замуж невтерпеж, то
private function sortHelper(x:int, y:int):int
{
var result:int = x - y;
return Math.abs(result) / result;
}
Очень опасный вариант, при равных x и y, result будет равен 0, а всем известно что 0/0=NaN, и вот тут спасает только приведение к int, т.к. int(NaN)=0. Но все это очень опасно, я бы так не делал.
Там и так везде int, ничего приводить не надо.
Dima_DPE
24.02.2012, 16:20
То что ты ничего не приводишь, не значит, что ничего не приводиться
А кто говорит, что ничего не приводится? И где опасность? Глючащий пример в студию.
Dima_DPE
24.02.2012, 17:29
Да будет это работать, БУДЕТ! Я и не говорил что не будет! Просто указал, что будет NaN. А NaN это NaN и с ним шутки плохи. По этому вариант опасный.
И вообще я всегда юзал такой вариант
private function sortHelper(x:int, y:int):Number
{
return x - y;
}
и вроде всегда верно сортировало. Конечно у меня все элементы в массивах конечные были и не nan.
В моей документации именно Number просят возвращять http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Vector.html#sort()
Во флеше нет "на самом деле" разницы между Number и int. Т.е. ее нет тогда, когда тип нужно определить динамически. Поэтому, не смотря на то, что в документации написано Number - возвращать int никто не запрещает, и наоборот тоже (естесственно, при условии, что проверок времени компиляции не делается).
Если бы такие проверки делались, то, очевидно, пришлось бы делать что-то типа:
Number(int(x - y));
или
isNaN(x - y) ? 0 : x - y;
кому что ближе.
ЗЫ. Опасность, как я уже и говорил, возникает тогда, когда разность приведет к переполнению, изза чего может поменяться знак.
Dima_DPE
24.02.2012, 19:27
Не стоит путать автоприведение типов и реальное отсутствие разницы. То что компилятор не ругается на автоприведение инта к флоуту и наоборот, это не значит, что за этим не стоит следить.
Холиварить не хочу, просто оставлю пару контра примеров, которые показывают что приведение типов происходит.
public function n():Number
{
return 0/0; // NaN
}
public function i():int
{
return 0/0; // 0
}
public function n2():Number
{
return 1.6; // 1.6
}
public function i2():int
{
return 1.6; // 1
}
Работает на vBulletin ® версия 3.7.3. Copyright ©2000-2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Copyright © 1999-2008 Flasher.ru. All rights reserved.