|
|
« Предыдущая тема | Следующая тема » |
Опции темы | Опции просмотра |
|
|
|||||
Логические операции как способ визуального упрощения кода
Добрый день, история такая:
Понадобился мне алгоритм быстрой проверки массива на одинаковые элементы с последующим удалением дубликатов. На Starkoverflow нашел следующий код, предназначенный для работы с массивом из строк (товарищу надо было удалить одинаковые имена): var a:Array = ["Tom", "John", "Susan", "Marie", "Tom", "John", "Tom", "Eva"]; a.sort(); var i:int = 0; while(i < a.length) { while(i < a.length+1 && a[i] == a[i+1]) { a.splice(i, 1); } i++; } В моем случае объекты в массиве - не строки, а именно объекты с несколькими полями. Удалять мне надо по id, то есть дополнительно нужно указывать, допустим, a[i].id Но в этом алгоритме есть хитрость, которая подтолкнула меня получше разобраться с булевыми операторами в AS3 (надо же подкрутить этот алгоритм под свой код) Условие не выполняется в двух случаях - когда [i]a и a[i+1] не равны, или если a[i+1] является null. По этой причине нельзя просто сделать так: var a:Array = [{id:"1"}, {id:"2"}, {id:"3"}, {id:"1"}, {id:"4"}, {id:"3"}, {id:"5"}, {id:"2"}]; var i:int = 0; while(i < a.length) { while(i < a.length+1 && a[i].id == a[i+1].id) { a.splice(i, 1); } i++; } Мне стало интересно, может ли логическа операция && возвратить существующее (не null) значение какого-либо параметра (Как это используется в Lua, например). Открываем документацию, читаем: Цитата:
var a:Array = [{id:"1"}, {id:"2"}, {id:"3"}, {id:"1"}, {id:"4"}, {id:"3"}, {id:"5"}, {id:"2"}]; var i:int = 0; while(i < a.length) { while(i < a.length+1 && a[i].id == (a[i+1] && a[i+1].id)) { a.splice(i, 1); } i++; } если expression1 (a[i+1]) принимает значение false или может быть преобразовано в false (в нашем случае в false преобразовывается null), то оператор возвращает это expression1, условие становится как в оригинальном алгоритме: если же a[i+1] не null, то возвращаем a[i+1].id, сравниваем с a[i] и все счастливы. Но все было бы слишком просто. По неизвестной мне причине такой способ работать отказался и я решил пойти дальше - протрейсить эти a[i+1].id следующим образом: var a:Array = [{id:"1"}, {id:"2"}, {id:"3"}, {id:"1"}, {id:"4"}, {id:"3"}, {id:"5"}, {id:"2"}]; var i:int = 0; while(i < a.length) { trace(a[i+1] && a[i+1].id); while(i < a.length+1 && a[i].id == (a[i+1] && a[i+1].id)) { a.splice(i, 1); } i++; } Очень странно - оператор работает правильно, сравниваем вроде одно и то же, а логика не работает Но если попробовать потрейсить так: var a:Array = [{id:"1"}, {id:"2"}, {id:"3"}, {id:"1"}, {id:"4"}, {id:"3"}, {id:"5"}, {id:"2"}]; var i:int = 0; while(i < a.length) { trace(a[i].id == (a[i+1] && a[i+1].id)); while(i < a.length+1 && a[i].id == (a[i+1] && a[i+1].id)) { a.splice(i, 1); } i++; } Итак, вопрос: Что я упускаю? Отвечать будет Друзь? |
|
|||||
Регистрация: Nov 2010
Сообщений: 497
|
Цитата:
После этого никакие приседания не нужны. А вообще вы путаете AS3 и LISP/LUA/PYTHON и прочие языки. В AS оператор && возвращает true/false, а не значение второго аргумента. |
|
|||||
maxkar, а как же тесты и документация?
попробуйте потрейсить var a:Array = [{id:"1"}, {id:"2"}, {id:"3"}, {id:"1"}, {id:"4"}, {id:"3"}, {id:"5"}, {id:"2"}]; var i:int = 0; while(i < a.length) { trace(a[i+1] && a[i+1].id); //Вот здесь будет выводить id, если элемент существует и null, если элемент null while(i < a.length+1 && a[i].id == (a[i+1] && a[i+1].id)) { a.splice(i, 1); } i++; } Цитата:
|
|
|||||
Регистрация: Nov 2010
Сообщений: 497
|
Ну в таком случае все правильно. У вас в вашем массиве нет двух элементов с одинаковым ID подряд. И только где-то на границе массива (i == a.length) вы получаете два null'а.
Цитата:
Цитата:
|
|
|||||
[+1 16.07.13]
[+4 16.07.13] Регистрация: Oct 2005
Сообщений: 217
|
Вы упускаете сортировку массива ,вот так у меня работает
var a:Array = [{id:"1"}, {id:"3"}, {id:"2"}, {id:"3"}, {id:"1"}, {id:"3"}, {id:"4"}, {id:"3"}, {id:"5"}, {id:"2"}]; var i:int = 0; a.sort(sortOnID); function sortOnID(a:Object, b:Object):Number { var aID:Number = a.id; var bID:Number = b.id; if(aID > bID) { return 1; } else if(aID < bID) { return -1; } else { return 0; } } while(i < a.length) { trace(a[i] && a[i].id); while(i < a.length+1 && a[i].id == (a[i+1] && a[i+1].id)) { a.splice(i, 1); } i++; } |
|
|||||
Да, с сортировкой я что-то перескочил.
Цитата:
belv, угу, спасибо! |
|
|||||
Регистрация: May 2008
Сообщений: 63
|
Если вам нужно иметь список объектов без повторений то вместо вот таких вот сориторовок/удалений, не проще ли данные изначально хранить в ассоциативном массиве(словаре)?
|
|
|||||
Кстати да, совсем забыл про словарь...
на самом деле там выйгрыш по производительности будет не особо заметен, ибо массив из максимум 10ти элементов, и это в худшем случае. Что так меньше одной мс на все операции, что по другому, тут больше идейный вопрос синтаксиса и логики был Спасибо за наводку в любом случае) Последний раз редактировалось KumoKairo; 04.07.2013 в 19:50. |
Часовой пояс GMT +4, время: 02:52. |
|
« Предыдущая тема | Следующая тема » |
Теги |
&& , логические операции |
Опции темы | |
Опции просмотра | |
|
|