3DCenter.ru

Здравствуйте, гость ( Вход | Регистрация )

2 страниц V   1 2 >  
Reply to this topicStart new topic
> ассоциативные массивы, или что-то что их заменяет
illusion21
сообщение 24/12/2011, 17:48
Сообщение #1


Уважаемый
Иконка группы

Группа: Пользователи
Сообщений: 917
Регистрация: 24/12/2003
Из: Тольятти
Пользователь №: 3 979



Добрый день.

Представьте себе 2 массива, в один я пишу некие данные, во второй массив пишу порядковый номер этой записи. Задача том чтобы в первом массиве все данные были уникальные. тоесть если такая запись уже была то дубль не добавляем, а во второй массив при этом мы пишем индекс записи которая уже когда то была сделана с аналогичным значением.

Вроде бы на первый взгляд все просто, AppendIfUnique и FindItem через которые мы фильруем записи и находим нужный индекс если вдруг оказалось что такое значение уже было раньше записано. Но на практике получается ОЧЕНЬ медленный рассчет. По мере наполнения массива новыми данными скрипту приходится перебирать 2 раза все элементы массива чтобы проверить на уникальность и найти нужный индекс. В итоге при количестве записей равным 40к скрипт думает около минуты.. а при 150к мне вообще не удалось дождаться результата так как замедление работы происходит по наростающей с каждой новой записью.
Для проверки уникальности было бы здорово использовать ассоциативный массив в котором бы заносилась запись с именем равным самому значению и присвоением в это поле номер индекса под которым призошла запись в целевой массив..... например array["345334"]=50.. таким образом не пришлось бы перебирать все записи обычного массива а только попытаться обратиться к элементу с нужным именем. И проверка была бы простой, обращаемся к записи под нужным именем, если такая существует то берем ее значение и на этом задача решена.

Возможно я плохо искал но я не нашел в максскрипте ничего похожего на ассоциативные массивы. Подскажите пожалуйста как еще можно реализоывать эту задачу
Go to the top of the page
 
+Quote Post
Lastjedi
сообщение 24/12/2011, 20:24
Сообщение #2


Учитель
Иконка группы

Группа: Участник
Сообщений: 322
Регистрация: 18/06/2002
Из: Москва
Пользователь №: 72



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

Искать дважды совсем не обязательно. Достаточно воспользоваться только функцией findItem.
например так:
Код
-- ValueArray - массив значений.
-- IndexArray - массив индексов.
-- newValue - новое значение.

local StoredValueIndex = findItem ValueArray newValue
if StoredValueIndex == 0 then (
    append ValueArray newValue
    append IndexArray ValueArray.count
)
else append IndexArray StoredValueIndex


Работает вполне прилично (в плане скорости).
Go to the top of the page
 
+Quote Post
illusion21
сообщение 24/12/2011, 21:03
Сообщение #3


Уважаемый
Иконка группы

Группа: Пользователи
Сообщений: 917
Регистрация: 24/12/2003
Из: Тольятти
Пользователь №: 3 979



ну как же не видно... внутренний алгоритм findItem перебирает весь массив при поиске значения... если в массиве 150 тысяч записей то поиск будет идти реально долго... а в случае с ассоциативными массивами нет такого перебора а идет напрямую обращение к записи... если запись не существует то пишем, если существует то не пишем...

а про то что 2 раза не перебирать это точно.. как то я не подумал, спасибо smile.gif

Сообщение отредактировал illusion21 - 24/12/2011, 21:04
Go to the top of the page
 
+Quote Post
Lastjedi
сообщение 24/12/2011, 21:13
Сообщение #4


Учитель
Иконка группы

Группа: Участник
Сообщений: 322
Регистрация: 18/06/2002
Из: Москва
Пользователь №: 72



Вообще-то я имел в виду использование двух массивов. Не вижу смысла в отдельном массиве значений и массиве индексов, если значения имеют фактически тот же тип, что и индексы (integer).
А по поводу array["345334"]=50, как по твоему интерпретатор найдет в "ассоциативном" массиве запись с идентификатором "345334" если не перебором?
Go to the top of the page
 
+Quote Post
[Vitus]
сообщение 24/12/2011, 21:18
Сообщение #5


Мастер
Иконка группы

Группа: Участник
Сообщений: 1 280
Регистрация: 30/05/2006
Пользователь №: 32 013



Можно ещё попробовать такой вариант: свалить всё в один массив, отсортировать его, и переписать в новый, опуская дубликаты. Таким образом избавляемся от дорогой операции поиска в массиве на каждом добавлении. Но сортировка достаточно дорогая операция, хотя и однократная.
Go to the top of the page
 
+Quote Post
illusion21
сообщение 24/12/2011, 21:49
Сообщение #6


Уважаемый
Иконка группы

Группа: Пользователи
Сообщений: 917
Регистрация: 24/12/2003
Из: Тольятти
Пользователь №: 3 979



QUOTE (Lastjedi @ 24/12/2011, 22:13) *
Вообще-то я имел в виду использование двух массивов. Не вижу смысла в отдельном массиве значений и массиве индексов, если значения имеют фактически тот же тип, что и индексы (integer).
А по поводу array["345334"]=50, как по твоему интерпретатор найдет в "ассоциативном" массиве запись с идентификатором "345334" если не перебором?


у меня на самом деле не два массива а один и вобще он трехмерный а зачем это нужно - одним словом нужно.
А по поводу того как оно ищется - при работе с ассоциативными массивами поиск идет по хэш ключам, что существенно быстрее перебора значений
Go to the top of the page
 
+Quote Post
ECXIMER
сообщение 24/12/2011, 21:49
Сообщение #7


пишу на С++ за еду
Иконка группы

Группа: Пользователи
Сообщений: 7 292
Регистрация: 08/12/2003
Из: компилятора
Пользователь №: 3 739



пробуй BigMatrix
Go to the top of the page
 
+Quote Post
illusion21
сообщение 24/12/2011, 21:51
Сообщение #8


Уважаемый
Иконка группы

Группа: Пользователи
Сообщений: 917
Регистрация: 24/12/2003
Из: Тольятти
Пользователь №: 3 979



ECXIMER, посмотрел в хэлпе и что-то не догнал как эту штуку можно приспособить для данной задачи

Сообщение отредактировал illusion21 - 24/12/2011, 21:53
Go to the top of the page
 
+Quote Post
ECXIMER
сообщение 24/12/2011, 23:37
Сообщение #9


пишу на С++ за еду
Иконка группы

Группа: Пользователи
Сообщений: 7 292
Регистрация: 08/12/2003
Из: компилятора
Пользователь №: 3 739



ну тогда bsearch() вместо finditem
Go to the top of the page
 
+Quote Post
illusion21
сообщение 25/12/2011, 00:21
Сообщение #10


Уважаемый
Иконка группы

Группа: Пользователи
Сообщений: 917
Регистрация: 24/12/2003
Из: Тольятти
Пользователь №: 3 979



bsearch насколько я понял работает только с отсортироваными массивами если я правильно понял из хэлпа... а у меня поиск должен идти по мере заполнения. Если я перед каждым заполнением буду сортировать массив, то толку от бисерча будет мало.. да и массив у меня многомерны.. если менять порядок в одном то во втором должно вообще меняться содержимое так как оно является перечислением индексов для записей в первом.

Или bsearch без сортировки умеет работать?
Go to the top of the page
 
+Quote Post
ECXIMER
сообщение 25/12/2011, 00:35
Сообщение #11


пишу на С++ за еду
Иконка группы

Группа: Пользователи
Сообщений: 7 292
Регистрация: 08/12/2003
Из: компилятора
Пользователь №: 3 739



не судьба )
Go to the top of the page
 
+Quote Post
illusion21
сообщение 25/12/2011, 00:42
Сообщение #12


Уважаемый
Иконка группы

Группа: Пользователи
Сообщений: 917
Регистрация: 24/12/2003
Из: Тольятти
Пользователь №: 3 979



эх... ))
начал тут C# изучать чтобы max SDK юзать в дальнейшем.. сам по себе язык более чем понятен, а вот про практическое его применение для 3d max я пока не нашел хороших уроков. Не подскажете где их можно найти? так чтобы прям с нуля наглядно было объяснено как писать штуки именно с использованием max SDK?
Go to the top of the page
 
+Quote Post
illusion21
сообщение 25/12/2011, 03:47
Сообщение #13


Уважаемый
Иконка группы

Группа: Пользователи
Сообщений: 917
Регистрация: 24/12/2003
Из: Тольятти
Пользователь №: 3 979



о блин. .оказывается SDK не поддерживает C#.. только С++
Go to the top of the page
 
+Quote Post
Lastjedi
сообщение 25/12/2011, 09:02
Сообщение #14


Учитель
Иконка группы

Группа: Участник
Сообщений: 322
Регистрация: 18/06/2002
Из: Москва
Пользователь №: 72



Цитата(illusion21 @ 24/12/2011, 22:49) *
...при работе с ассоциативными массивами поиск идет по хэш ключам, что существенно быстрее перебора значений

Использование хэш ключей - это разновидность сортировки. Ничто не мешает реализовать тоже самое ручками. Причем если данные (как в примере - целое число), то никакой специальной хэш функции и не потребуется. Просто разбиваешь свой массив на несколько по какому-либо признаку (четные-нечетные, оканчивающиеся на 0, 1, 2, 3 и т.д и т.п. признаков можно много напридумывать). Тогда время на поиск сократится за счет ограничения области поиска.

Вдогонку пример:
Код
-- nSubArrays - Количество подмассивов, в которых будут сохраняться данные

local ArrayIndex = (mod newValue nSubArrays) as integer + 1

local StoredValueIndex = findItem ValueArray[ArrayIndex] newValue
if StoredValueIndex == 0 then (
    append ValueArray[ArrayIndex] newValue
    append IndexArray #(ArrayIndex, ValueArray[ArrayIndex].count)
)
else append IndexArray #(ArrayIndex, StoredValueIndex)

Чем больше общее количество значений, тем большее число массивов имеет смысл использовать. Например, если при количестве уникальных значений в 1 000 000, задать nSubArrays = 10000 заполнение происходит всего за несколько секунд.

Сообщение отредактировал Lastjedi - 25/12/2011, 09:03
Go to the top of the page
 
+Quote Post
illusion21
сообщение 25/12/2011, 09:58
Сообщение #15


Уважаемый
Иконка группы

Группа: Пользователи
Сообщений: 917
Регистрация: 24/12/2003
Из: Тольятти
Пользователь №: 3 979



спасибо, попробую smile.gif правда это только в примере обсуждаемом в этой теме значение является целым числом. В моем случае значение является вектором.

Сообщение отредактировал illusion21 - 25/12/2011, 10:00
Go to the top of the page
 
+Quote Post
Bots
сообщение Системное сообщение






2 страниц V   1 2 >
Reply to this topicStart new topic

1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 



RSS Текстовая версия Сейчас: 25/04/2024 - 20:39