Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   ActionScript 3.0 (http://www.flasher.ru/forum/forumdisplay.php?f=83)
-   -   работа с изменяющимися массивами (http://www.flasher.ru/forum/showthread.php?t=146515)

elzone 10.11.2010 11:41

работа с изменяющимися массивами
 
Здравствуйте.
есть такая задача.
на вход флешки из внешней программы поступаем строка значений объекта вида:
1,1,200,250;0,2,600,300;2,22,100,500;
где первое значение - это тип объекта
второе значение - ID объекта
третье значение - координата Х
четвертое значение - координата Y.

я эту строку при помощи .split(";") загоняю в массив
потом пробегаю по этому массиву и расставляю соответствующие типы в нужные координаты, добавляя на сцену при помощи addChild(нужный тип)

но стока значений периодически меняется - и значения в ней тоже могут быть разными.

каким образом отследить что оставить на сцене, что удалить и что добавить

на мой взгляд - это нужно как то выделять все в разные массивы, но мне не совсем понятно как потом удалить нужный объект со сцены и как оставить на сцене те объекты, которые остались в строке значений.


ломаю голову - уже закипел.
может кто то подскажет направление

-De- 10.11.2010 11:50

Ну вы как-то храните айдишники того, что у вас на сцене. Тогда обьекты с новыми айдишниками - добавить, со старыми - оставить, каких нет - удалить. В чём проблема?

leofit 10.11.2010 11:54

Самый простой вариант (но не самый лучший) - удалить ВСЁ и заново добавить из нового массива

elzone 10.11.2010 12:01

re: leofit
в том то и дело что удалять все не надо. те объекты, ID которых сново есть в строке значений должны бить оставлены.

re: -De-
я не совсем могу понять как это мне сделать. сравнить две строки, значения которые совпали пометить в массив - оставить.
а как потом выделить объекты которые надо удалить и те что добавить.

плюс как удалить объект, если его ID и индекс при добавлении через addChild могу не совпадать

alatar 10.11.2010 12:09

При добавлении добавляйте объекты в хэш (Object), при получении строки проверяйте, есть ли объект такого типа (ну или какой там у вас параметр является уникальным) в хэше, просто передвигаете его, если нет создаете новый и добавляете в словарь. Все типы (непосредственно строка которая обозначает тип) которые есть в полученных значениях складываете попутно в другой хэш (временный). После того как все значения будут обработаны, зачишаете основной хэш: проходитесь по основному хешу и если в нем попадается тип, которого нет во временном хэше, убираете объект такого типа из списка отображения и удаляете его из хэша.

-De- 10.11.2010 12:16

Ну сделать подумав мозжечком и такой-то матерью три набора айдишников, один - новые из массива, второй - старые, которые на сцене, третий - все, какие есть. Для всех айдишников из 3-го: если айдишник есть в 1-м, но нет во 2-м, то что делаем? если есть во 2-м, но нет в 1-м, то что делаем? если есть в 1-м и втором, то что делаем? Если нет ни в 1-м ни во 2-м, то стреляемся, т.к. не понятно, как он тогда попал в 3-й.
Хранить соответствие ID-обьект, индекс обьекта в дисплей листе - часто ненадёжное число, удалять не по индексу, а по обьекту, removeChild(objByID[ID])
Собсно надо уметь использовать Object и цикл for(var key:String in myObject) по нему. Хотя можно и на массивах.

bav 10.11.2010 12:18

Например так:
1) После прихода первой строки у нас формируется массив объектов вида
{type:0 , id:23 , _x:150 , y:75 , rest:false}
2) Когда приходит новая строка, мы получаем из нее массив объектов вида
{type:0 , id:23 , _x:150 , y:75}
3) Проверяем по id, присутствуют ли элементы из нового массива в старом. Если элемент присутствует, смотрим, нужно ли изменить его координаты и устанавливаем значение rest в true. Если элемента с таким id нет, то добавляем его в массив и опять-таки устанавливаем rest в true.
4) После перебора всех элементов второго массива, проходимся по первому массиву и удаляем все элементы, у которых rest == false.

P.S. Перед перебором очередной пришедшей строки, у всех элементов массива, разумеется, свойство rest нужно сбрасывать на false.

TanaTiX 10.11.2010 12:18

Думаю, что в данной ситуации в самый раз будет применение Dictionary вместо Array, Vector или Object

alatar 10.11.2010 12:30

Как раз в данной ситуации Dictionary не удобен, ввиду того, что у него в качестве ключа выступают объекты вместо id

dimarik 10.11.2010 12:44

Что-то типа

Код AS3:

var o = dataBase.getObjectById(id:String):CustomObject;
 
if (!o) {
    o = new CustomObject();
    o.type = type;
    o.id = id;
    dataBase.addObject(o);
}
 
o.moveTo(x, y);

DataBase#

Код AS3:

var list:Object = {};
 
function getObjectById(id:String):CustomObject {
    return list[id] as CustomObject;
}


elzone 10.11.2010 14:29

re -De-

подскажи пожалуйста - как добавлять объекты в дерево DisplayObject и сохранять соответствие этого объекта и его id

TanaTiX 10.11.2010 14:34

Я это примерно так вижу:
Код AS3:

var dict = new Dictionary(true);
dict[id]=new YouObject(type, x, y);
 
function change(id:String, x, y):Boolean{
        if(dict[id]){
                dict[id].setParams(x, y);
                return true;
        }else{
                return false;
        }
}


-De- 10.11.2010 15:12

Добавлять с помощью addChild.
сохранять соответствие типа
Код AS3:

//где-то там переменная класса или статик может даже - хранилка
public var list:Object = new Object();
//собсно сохранять
list[ID] = obj;
//нетривиальная (для новичков и не читающих доки) вещь - как удалять это соответствие
delete list[ID];

Ну в общем dimarik не написал addObject, а вы не знаете, как работать с Object? бида
Код AS3:

function addObject(id:String, obj:CustomObject ):void{
    if(id in list) {
        //фигня случилась, уже есть ваш айдишник, забыли удалить или ещё где логика страдает
        throw new Error("duplicate id");
    }
    list[id] = obj;
}

TanaTiX, а где там сохранение, зачем всё остальное и почему Dictionary, а не Object и не Array?

TanaTiX 10.11.2010 16:21

Не Array и не Vector, т.к. проще обратиться по имени, чем перебирать все элементы до поиска нужного.
Почему не Object - мне кажется, что Dictionary более специфичен для указанной задачи. Тут, собственно, нет уверенности, скорее личное предпочтение. К тому же Object использует в качестве ключа исключительно строку и возможность использования слабых ссылок. Если есть другие аргументы - было бы интересно.

Psycho Tiger 10.11.2010 16:38

Цитата:

Почему не Object - мне кажется, что Dictionary более специфичен для указанной задачи.
Object - строковой хэш, Dictionary - объектный. Тут не может быть "более" специфичных, подходит всегда только один. (в плане правильности подхода - не стоит ради строкового хэша делать объектный)

-De- 10.11.2010 19:09

А Array/Vector - это в некотором роде числовой мап, а айдишник у нас что? Кстати, операция узнавания значения массива по индексу - она быстрее всех этих ваших хешэй (я, кстати, думаю, что индусы там дерево хорошо если сбалансированное сделали, а не хэш). Ну у него минусы, в общем, если индекс большой, то и массив большой. Хотя есть подозрение, что таки Array он на самом деле не массив, а мап и он память вроде не жрёт тоннами, если завести в нём 1 эл-т с номером 100000000.
Dictionary лучше рассматривать как ссылочный мап, т.е. ключ - ссылка, хотя он допилен до общего мапа. Потому он тяжелей. Установка использования слабых ссылок, кстати, просто не работает для тех эл-тов Dictionary, где ключ - "простой" обьект (на ваше счастье, потому что GC иначе сожрал бы связь).

alatar 10.11.2010 19:34

Цитата:

Vector - это в некотором роде числовой мап
Вектор, это таки, далеко не мап :)

Добавлено через 7 минут
Разница в скорости тоже не особо впечатляет: http://jacksondunstan.com/articles/855
60мс на 1000000 операций, можно не принимать в расчет.

TanaTiX 10.11.2010 19:46

А что такое мап?
Код AS3:

не стоит ради строкового хэша делать объектный

можно поподробней, в чем в данном случае минус Dictionary? И когда тогда его использовать имеет смысл?
Цитата:

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

Dictionary лучше рассматривать как ссылочный мап, т.е. ключ - ссылка, хотя он допилен до общего мапа. Потому он тяжелей.
Цитата:

Установка использования слабых ссылок, кстати, просто не работает для тех эл-тов Dictionary, где ключ - "простой" обьект (на ваше счастье, потому что GC иначе сожрал бы связь).
А вот на счет этого можно поподробней?

Psycho Tiger 10.11.2010 20:00

-De-, Вы знаете как массивы хранятся в флеш плеере? Я не знаю. Догадки тут неуместны - если говорить о лоу-левеле за ширмой abc кода, то и говорить о нём. Короче, программиста не должны волновать низкоуровневые особенности кода, в который он транслируется.

Мы имеем что имеем. Array можно рассматривать как надежный массив (вектор) указателей, с оговорками к простым типам. Vector - аналогично. Только оно нам надо? Меня как-то не очень волнует какой технологией реализуется что-то нативное.

Цитата:

Хотя есть подозрение, что таки Array он на самом деле не массив, а мап и он память вроде не жрёт тоннами, если завести в нём 1 эл-т с номером 100000000.
С точки зрения юзера задав 100000 элемент 99999 создадутся, потому что length будет говорить 1000000. А хэлп гласит
Цитата:

Неотрицательное целое число, которым задается количество элементов в массиве.
Цитата:

можно поподробней, в чем в данном случае минус Dictionary? И когда тогда его использовать имеет смысл?
Когда нужен хэш, где ключами являются объекты.
Цитата:

В данном случае у нас нет индекса, т.е. нужно сравнить все элементы с некоторым значением.
Почему же, есть хэш-функции свёртки чего-то там в число, которое будет являться индексом. Я не очень знаю как это дело работает, но там не банальное сравнение.

Цитата:

А вот на счет этого можно поподробней?
Цитата:

Установка использования слабых ссылок, кстати, просто не работает для тех эл-тов Dictionary, где ключ - "простой" обьект (на ваше счастье, потому что GC иначе сожрал бы связь).
Простые типы передаются по значению, в контексте AS3 говорить о ссылках на простой тип вообще говорить бессмысленно.

TanaTiX 10.11.2010 20:40

Т.е. в данном случае, что Dictionary, что Object - один хрен?
Цитата:

Почему же, есть хэш-функции свёртки чего-то там в число, которое будет являться индексом. Я не очень знаю как это дело работает, но там не банальное сравнение.
А есть ссылочки на тему?

Psycho Tiger 10.11.2010 20:47

Цитата:

Т.е. в данном случае, что Dictionary, что Object - один хрен?
Dictionary - объектный хэш, т.е. можно пихать туда объекты.
"1" "1" - по идее, это 2 разных объекта. Но почему то он ведёт себя как один в контексте Dictionary мне неясно.
UPD: хотя, я, кстати, погорячился причем сильно. "1"==="1", а очевидно что если взять значение от одного ключа два раза - оно совпадёт. Так что всё вполне понятно.

Например, здесь:
http://ru.wikipedia.org/wiki/%D0%A5%...B8%D1%86%D0%B0
Цитата:

Выполнение операции в хеш-таблице начинается с вычисления хеш-функции от ключа. Получающееся хеш-значение i = hash(key) играет роль индекса в массиве H.

-De- 10.11.2010 21:44

Цитата:

Сообщение от Psycho Tiger (Сообщение 948894)
-De-, Вы знаете как массивы хранятся в флеш плеере? Я не знаю. Догадки тут неуместны - если говорить о лоу-левеле за ширмой abc кода, то и говорить о нём. Короче, программиста не должны волновать низкоуровневые особенности кода, в который он транслируется.

Вам пофик, жрёт ваш массив гиг оперативки или килобайт? =)

Мап (map) в данном случае переводится как "ассоциативный массив", ну или отображение. Хэш (hash table, hash map) - один из алгоритмов его реализации.

Как работают слабые ссылки у Dictionary можно понять самому, написав примерчик, типа этого (правда только для дебаг плеера работает, для обычного чуть сложнее будет).
Код AS3:

package {
        import flash.display.*;
        import flash.events.*;
        import flash.utils.*;
        import flash.system.*;
 
        public class Main extends Sprite {
                public var dict:Dictionary = new Dictionary(true);
 
                public function Main() {
                        var s:String = "test";
                        var spr:Sprite = new Sprite();
                        var val:Sprite = new Sprite();
 
                        //addChild(val);//попробуйте пооткомментировать и посмотреть
                        //addChild(spr);
 
                        dict[s] = 1;
                        dict[spr] = val;
                        System.gc();
                        addEventListener(Event.ENTER_FRAME, ef);
                }
                public function ef(ev:Event):void {
                        for (var key:Object in dict) trace(key, dict[key]);
                        removeEventListener(Event.ENTER_FRAME, ef);
                }
        }
}


Psycho Tiger 10.11.2010 22:00

О боже. Простой тип может существовать только в связке со сложным (ну или статикой, но класс тоже можно считать сложным типом), причем он не может никуда ссылаться. Он просто есть в данном месте. И если это данное место удалить - то удалится и простой тип.

Цитата:

Вам пофик, жрёт ваш массив гиг оперативки или килобайт? =)
Приведите цифры сколько что ест памяти при какой загрузке.
Конкретно у меня когда нужен объектный хэш - используется диктионари, когда строковой - обджект, чего и Вам желаю. Поэтому кто сколько "жрёт" меня не волнует - я использую инструмент там, где надо. А разницу в памяти между Obect и Dictionary юзер и не заметит - на утечках фп улетит куда больше.

TanaTiX 10.11.2010 22:02

-De-, спасибо за пример, наглядно и доступно.
Цитата:

Например, здесь:
http://ru.wikipedia.org/wiki/%D0%A5%...B8%D1%86%D0%B0
Таким образом может получится, что массив/вектор в итоге дешевле выйдет?
Самому сейчас нет желания тест скорости писать, может у кого есть ссылка по теме? Помню как-то видел, только не помню где.

Psycho Tiger 10.11.2010 22:04

Код AS3:

                        var o:Object = { };
                        var d:Dictionary = new Dictionary();
 
                        trace(getSize(o)); //24
                        trace(getSize(d)); //32
 
                        var s:String = "1";
                        var v:String = "v";
 
                        o[s] = v;
                        d[s] = v;
 
                        trace(getSize(o)); //32
                        trace(getSize(d)); //40

+4 байта на ссылку под ключ, +4 байта на ссылку под значение с каждым добавлением и там и там.
Поздравляю, Вы спасли 8 байт.
UPD: хотя, не 8, может чуть больше, возможно эти 8 байт - 2 ссылки, которые getSize считает по 4 байта. Но я думаю мысль ясна.

Добавлено через 44 секунды
Цитата:

Таким образом может получится, что массив/вектор в итоге дешевле выйдет?
Вектор/массив будет всегда быстрее хеша. Особенно если заполнение будет постепенным с 0.

-De- 10.11.2010 22:37

Цитата:

Сообщение от Psycho Tiger (Сообщение 948919)
Конкретно у меня когда нужен объектный хэш - используется диктионари, когда строковой - обджект, чего и Вам желаю.

А когда нужен числовой?
Я про то, что такие "низкоуровневые особенности кода" могут таки делать хорошую разницу =)
Если Array - ассоциативный массив на самом деле, то для того, чтобы поиметь элемент с индексом в 1000000000 ему таки меньше памяти понадобится, чем если он обычный массив. =)

alatar 10.11.2010 22:43

Теоретики, блин :) хоть кто-то из вас тест по ссылке смотрел?
60мс на 1000000 итераций это для вас хорошая разница?

Psycho Tiger 10.11.2010 22:54

Цитата:

Сообщение от alatar (Сообщение 948930)
Теоретики, блин :) хоть кто-то из вас тест по ссылке смотрел?
60мс на 1000000 итераций это для вас хорошая разница?

А мы про память :quiet:
Цитата:

А когда нужен числовой?
Array/Vector
Цитата:

Если Array - ассоциативный массив на самом деле, то для того, чтобы поиметь элемент с индексом в 1000000000 ему таки меньше памяти понадобится, чем если он обычный массив. =)
Код AS3:

var a:Array = [];
trace(getSize(a)); //40
a[1000000] = 1;
trace(getSize(a)); //48

И что это меняет? Для меня - ничего, я не работаю с памятью напрямую.
Код AS3:

var i:int = 10000000;
                        var a:Array = [];
 
                        var t:int = getTimer();
                        while (i--) a[i] = 1;
                        trace(getTimer() - t);
 
                        a = [];
                        t = getTimer();
                        for (i = 0; i < 10000000; i++) a[i] = 1;
                        trace(getTimer() - t);

Код:

2020
548

А вот это заставляет считать меня Array чуть менее ассоциативным.

И бить по пальцам тех, кто забивает в массивы значения не с 0. Во всяком случае тех, кто специально.

TanaTiX 10.11.2010 23:47

Psycho Tiger, попробуй так:
Код AS3:

for (i = 10000000; i > 0; i--)

вместо while - результат будет отличаться, но уже не так значительно

Psycho Tiger 10.11.2010 23:53

И правда, забавно, спасибо. Видимо, это издержки, что > 0 работает быстрее, чем насильно конвертировать в Boolean. Однако, суть теста не меняется )

TanaTiX 11.11.2010 00:52

Я еще читал, что флеш отнимает медленнее, так что теоретически возможно, что разница стремится к 0.

Psycho Tiger 11.11.2010 01:19

Цитата:

Сообщение от TanaTiX (Сообщение 948953)
Я еще читал, что флеш отнимает медленнее, так что теоретически возможно, что разница стремится к 0.

Разница чего?

TanaTiX 11.11.2010 01:32

разница в скорости для ситуации, описанной в 28м посте

Psycho Tiger 11.11.2010 01:39

Нет. Разница есть, и почти в 4 раза.

-De- 11.11.2010 09:39

Цитата:

Сообщение от Psycho Tiger (Сообщение 948933)
Array/Vector


Код AS3:

var a:Array = [];
trace(getSize(a)); //40
a[1000000] = 1;
trace(getSize(a)); //48

И что это меняет? Для меня - ничего, я не работаю с памятью напрямую.

Теперь то же самое проделайте с вектором и расскажите, что разницы нет =)

elzone 11.11.2010 11:01

спасибо всем за комменты. это все помогло в итоге разобраться в проблеме.

Psycho Tiger 11.11.2010 13:05

Цитата:

Сообщение от -De- (Сообщение 948987)
Теперь то же самое проделайте с вектором и расскажите, что разницы нет =)

Вектор себя по другому ведёт - чтобы писать в куда-то далеко в него сначала нужно его расширить, тем же сеттером length, при этом getSize`у положить на его длину и количеством элементов в нём. Он ведёт себя как настоящий массив.

-De- 11.11.2010 13:40

И что это меняет? (с)

Psycho Tiger 11.11.2010 13:46

Цитата:

Сообщение от -De- (Сообщение 949029)
И что это меняет? (с)

Для меня - ничего.

Вы спросили - я ответил )

alatar 11.11.2010 14:08

Цитата:

Вектор себя по другому ведёт - чтобы писать в куда-то далеко в него сначала нужно его расширить, тем же сеттером length, при этом getSize`у положить на его длину и количеством элементов в нём. Он ведёт себя как настоящий массив.
Не надо наговаривать на getSize. Он очень ответственный :)
Код AS3:

var vec:Vector.<String> = new Vector.<String>();               
trace(getSize(vec)); //60
 
vec.push("a");
trace(getSize(vec)); //64
 
vec.length = 1000000;               
vec[1000000] = "a";
trace(getSize(vec)); //5000064



Часовой пояс GMT +4, время: 18:12.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2026, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.