PDA

Просмотр полной версии : Работа с коллекциями


zorexundra
12.09.2011, 11:41
Здравствуйте!
Помогите решить задачу.
Есть множество объектов типа ArrayCollection, со своей структурой.
Для ускорения работы с данными, я хочу структуировать представление ArrayCollection в соответствии со своими задачами.
Для этого я формирую списки индексов элементов ArrayCollection с помощью метода getItemIndex().
Но вот незадача: после сортировки ArrayCollection элементы меняют свой индекс.
Подскажите, как можно проиндексировать объект ArrayCollection, чтобы потом по индексу элемента можно было обратиться к последнему, не взирая на операции вставки, сортировки, удаления.

GBee
12.09.2011, 12:54
Ох вы написали. Может параллельно набивать/удалять эти элементы в хеш-таблицу?

zorexundra
12.09.2011, 13:07
Ох вы написали. Может параллельно набивать/удалять эти элементы в хеш-таблицу?
Думаю такой вариант вполне рабочий. Но это приведёт к дублированию данных и увеличению потребляемой приложением памяти. Также придётся придумать алгоритм синхронизирующий два источника данных. Перефразируя фразу "Шурик, Вы комсомолец? Это же не наш метод!" из известного кинофильма:
- GBee, Вы Flash-разработчик? Это же не наш метод! :)

GBee
12.09.2011, 13:19
Почему, просто будет две ссылки на один и тот же объект. Синхронизация - работы на 10 минут. Я за быстродействие :о)

Добавлено через 2 минуты
У себя постоянно использую массив+таблица. Массив для массовых операций, таблица - быстро вытащить нужный элемент.

zorexundra
12.09.2011, 13:46
GBee, поправьте меня, если я ошибаюсь:
var testArCol:ArrayCollection = new ArrayCollection(new Array(2,1,8,5));
var elementTestArCol:Object = testArCol.getItemAt(0);
trace(elementTestArCol); // 2
testArCol.removeItemAt(0);
trace(testArCol.getItemAt(0)); // 1
trace(elementTestArCol); // 2
Тобишь, метод getItemAt() вернул нам объект, а не ссылку на него.
Возможно я чего-то недопонимаю в механизме присвоения ссылок в AS.

GBee
12.09.2011, 14:06
В ActionScript 3.0 все аргументы передаются ссылками, поскольку все значения хранятся как объекты. Однако объекты, принадлежащие примитивным типам данных, к которым относятся Boolean, Number, int, uint, и String, имеют специальные операторы, которые позволяют воспроизвести поведение объектов при передаче аргументов значениями.

Отсюда (http://help.adobe.com/ru_RU/ActionScript/3.0_ProgrammingAS3/WS5b3ccc516d4fbf351e63e3d118a9b90204-7f56.html)

zorexundra
12.09.2011, 14:36
function passByRef(objParam:Object):void {
var testAr:Array = new Array(objParam.x, objParam.y);
objParam.x++;
objParam.y++;
trace(objParam.x, objParam.y);
trace(testAr[0], testAr[1]);
}
var objVar:Object = {x:10, y:15};
trace(objVar.x, objVar.y); // 10 15
passByRef(objVar); // 11 16 10 15
trace(objVar.x, objVar.y); // 11 16
GBee, каким образом я должен на основании заданной коллекции создать коллекцию, "удобоваримую" для меня, не копируя значения исходных данных?
...Хм. Разобрался - var testAr:Array = new Array(objParam);

Всё-таки хочется работать с исходным объектом ArrayCollection не прибегая к методам перебора.
Есть такая возможность в Flex-framework?

GBee
12.09.2011, 14:57
Всё-таки хочется работать с исходным объектом ArrayCollection не прибегая к методам перебора.
Есть такая возможность в Flex-framework?

Нихт понимайтен :о)) Перефразируйте, пожалуйста. А что вам нужно в итоге? Не в вашем виденьи, а по ТЗ/таску? Может вы зря мучаетесь.

zorexundra
12.09.2011, 15:22
Есть множество ArrayCollection соответствующих таблицам серверной БД.
Всё это множество нужно систематизировать на стороне клиента и свести в один ArrayCollection.
В этом конечном ArrayCollection должны быть значения идентифицирующие исходные итемы множества ArrayCollection (теперь я так понимаю ссылки на эти итемы), по которым можно быстро обратиться к исходным данным.
Механизм наподобие реляционных БД: есть идентификатор поля, по нему получаем доступ к строке таблицы. Или механизм хеш-таблицы.
Цель - ускорить работу с данными учитывая переменные условия.

Кажется, Вы помогли мне в формировании понимания путей реализации:
необходимо создать коллекцию ссылок на исходные элементы.
Но остаётся иллюзия, что можно как-то пометить элементы исходных коллекций, чтобы потом обратиться к ним по этим меткам. Такой путь более приятен для моих стереотипов.

saprahan
12.09.2011, 15:32
Но остаётся иллюзия, что можно как-то пометить элементы исходных коллекций, чтобы потом обратиться к ним по этим меткам. Такой путь более приятен для моих стереотипов.

Это не иллюзия. На практике такой кейс и вправду встречается. Рекомендую при инициализации коллекции заводить также мапу: ключ->айтем. Можно, например, экстендить ArrayCollection, добавить параметр itemsMap, и в конструкторе ArrayCollection'a (а также, возможно в оверрайде метода refresh) прописать инициализацию мапы из сорса. Назвать MappedArrayCollection.

Dimitry_II
12.09.2011, 15:38
Что-то мне кажется, что все это отдает то ли заумностью, то ли бредом.

Что мешает отдать с сервера коллекции с идентефикаторами? А на клиенте сортировать с помощью Sort и вытаскивать объект по идентефикатору? Если таки это сложно - "множество ArrayCollection соответствующих таблицам серверной БД", то все равно отдавать с сервера коллекцию DTO, в которую уже будут всунуты данные с разных таблиц и назначены идентефикаторы для предоставления уникального доступа. Мудрить с двумя структурами на клиенте - на кой?

Кроме этого - коллекция с сервера отдается в зависимости от построения списка на сервере (допустим, ArrayList и LinkedList дадут/могут дать разный порядок), однако при формировании объекта ArrayCollection в его свойстве source типа Array порядок вложенных объектов будет постоянен вне зависимости от показываемой сортировки. По крайней мере, это может избавить от создания параллельной структуры для коллекции.

zorexundra
12.09.2011, 15:48
Что мешает отдать с сервера коллекции с идентефикаторами? А на клиенте сортировать с помощью Sort и вытаскивать объект по идентефикатору?
А можно какой-нибудь простенький пример кода?
Среда разработки - Flex-AMFPHP-MySQL.

Добавлено через 23 минуты
Можно, например, экстендить ArrayCollection, добавить параметр itemsMap, и в конструкторе ArrayCollection'a (а также, возможно в оверрайде метода refresh) прописать инициализацию мапы из сорса
Если при разработке конечных приложений используются принципы ООП, то возможно была выбрана не та IDE :)
Можно, также, пример кода?
Сама по себе идея, на мой взгляд, интересная.

saprahan
12.09.2011, 16:46
А можно какой-нибудь простенький пример кода?
Среда разработки - Flex-AMFPHP-MySQL.

Добавлено через 23 минуты

Если при разработке конечных приложений используются принципы ООП, то возможно была выбрана не та IDE :)
Можно, также, пример кода?
Сама по себе идея, на мой взгляд, интересная.

Интересно, при чем здесь IDE ?

Добавлено через 3 минуты
Очень здравая идея с построением общей мапы есть в HierarchicalCollectionView.Регулярно проходить про древовидной структуре и вправду дорого - цикл в цикле. Там как раз и строится мапа как хелпер. Правда лишь для открытых нод, что на практике несет в себе мало пользы.

zorexundra
12.09.2011, 16:59
saprahan, это шутка в ответ на предложение дорабатывать исходные объекты.
Поделитесь мнением.
Предположим есть экземпляр пользовательского класса MappedArrayCollection расширяющий ArrayCollection.
Экземпляр слушает событие "collectionChange". По этому событию MappedArrayCollection циклом for each перебирает все элементы массива source и присваивает им идентификаторы. MappedArrayCollection имеет публичный метод отдающий элемент source по внешнему запросу с параметром идентификатора.
В source 30000 элементов. Для каждого элемента в MappedArrayCollection задаётся 10 переменных со значением ключа-идентификатора. Насколько быстрым будет этот класс? Не повесит-ли он приложение?
Не проще-ли создать отдельную хеш-таблицу со ссылками на элементы ArrayCollection.source?

saprahan
13.09.2011, 14:40
saprahan, это шутка в ответ на предложение дорабатывать исходные объекты.
Поделитесь мнением.
Предположим есть экземпляр пользовательского класса MappedArrayCollection расширяющий ArrayCollection.
Экземпляр слушает событие "collectionChange". По этому событию MappedArrayCollection циклом for each перебирает все элементы массива source и присваивает им идентификаторы. MappedArrayCollection имеет публичный метод отдающий элемент source по внешнему запросу с параметром идентификатора.
В source 30000 элементов. Для каждого элемента в MappedArrayCollection задаётся 10 переменных со значением ключа-идентификатора. Насколько быстрым будет этот класс? Не повесит-ли он приложение?
Не проще-ли создать отдельную хеш-таблицу со ссылками на элементы ArrayCollection.source?

Я вам это и написал, читайте внимательно. Слушать эвент и что то по нему делать - это вы уже придумали сами ))) ROFL

BTW экстендить нативные FLEX компоненты при более-менее сложной разработке приходится регулярно. Не стоит этого пугаться.

zorexundra
13.09.2011, 17:50
saprahan, представьте, на станции авто-техобслуживания механик говорит Вам:
- Ща доработаем вашу колымагу! :)
Вот набросал. Что скажите?:package
{
import mx.collections.ArrayCollection;
import mx.events.CollectionEvent;
public class MappedArrayCollection extends ArrayCollection
{
public var arrayElement:Object = new Object();
public function MappedArrayCollection(source:Array=null)
{
super(source);
addEventListener(CollectionEvent.COLLECTION_CHANGE, collectionChangeHandler);
}
override public function set source(s:Array):void
{
super.source = s;
for each(var el:Object in s){
arrayElement["e"+el.ID]=el;
}
}
private function collectionChangeHandler(event:CollectionEvent):void
{
switch(event.kind){
case "add":
arrayElement["e"+event.items[0].ID]=event.items[0];
break;
case "remove":
delete arrayElement["e"+event.items[0].ID];
break;
}
}
}
}