Таким образом, у меня есть список слов (весь английский словарь).
Для игры соответствия слова, когда игровые движения часть я должен проверить весь словарь, чтобы видеть, если слово, что сделанный плеер существует в словаре. Я должен сделать это как можно быстрее. просто итерация через словарь является слишком медленной.
Каков самый быстрый алгоритм в AS3 для поиска длинного списка как это для соответствия, и какой тип данных я должен использовать? (т.е. массив, объект, Словарь и т.д.)
Сначала я бы выбрал объект, который представляет собой хеш-таблицу (по крайней мере, с точки зрения хранения).
Итак, для каждого слова в вашем списке сделайте запись в объекте словаря и сохраните его значение true.
Затем вам просто нужно проверить, является ли данное слово ключевым в вашем словаре, чтобы узнать, является ли слово, выбранное пользователем, правильным или нет.
Это работает очень быстро в этом простом тесте (с 10 000 000 записей):
var dict:Object = {};
for(var i:int = 0; i < 10000000; i++) {
dict[i] = true;
}
var btn:Sprite = new Sprite();
btn.graphics.beginFill(0xff0000);
btn.graphics.drawRect(0,0,50,50);
btn.graphics.endFill();
addChild(btn);
btn.addEventListener(MouseEvent.CLICK,checkWord);
var findIt:Boolean = true;
function checkWord(e:MouseEvent):void {
var word:String;
if(findIt) {
word = "3752132";
} else {
word = "9123012456";
}
if(dict[word]) {
trace(word + " found");
} else {
trace(word + " not found");
}
findIt = !findIt;
}
Создание словаря занимает немного больше времени, но поиск выполняется почти мгновенно.
Единственное предостережение: вам придется учитывать определенные ключи, которые пройдут проверку и не обязательно будут частью вашего списка слов. Такие слова, как toString, prototype и т. Д. Их всего несколько, но имейте это в виду.
Я бы попробовал что-то подобное с вашим реальным набором данных. Если все работает нормально, то у вас действительно простое решение. Сходи выпей пива (или как хочешь).
Теперь, если вышеупомянутое не работает после тестирования с реальными данными (обратите внимание, я создал список с числами, преобразованными в строки для простоты), тогда пара вариантов, которые я забываю:
1) Разделите первый dict
на набор словарей. Итак, вместо того, чтобы иметь все слова в dict
, имейте словарь для слов, которые начинаются с 'a', другого для 'b' и т. Д. Затем, прежде чем искать слово, проверьте первый символ на знаю, где это найти.
Что-то вроде:
var word:String = "hello";
var dictKey:String = word.charAt(0);
// actual check
if(dict[dictKey][word]) {
trace("found");
} else {
trace("not found");
}
В конце концов, при необходимости, можно будет переделать. Я.e, заставьте dict ['a']
указать на другой набор словарей, проиндексированных первыми двумя символами. Итак, у вас будет dict ['a'] ['b'] [wordToSearch]
. Есть несколько возможных вариантов этой идеи (вам также нужно будет придумать некоторую стратегию, чтобы справиться со словами из двух букв, такими как, например, «быть»).
2) Попробуйте выполнить двоичный поиск . Проблема в том, что вам сначала нужно отсортировать список заранее. Вы должны сделать это только один раз, так как нет смысла удалять слова из вашего диктофона. Но с миллионами слов это могло бы быть менее интенсивным.
3) Попробуйте необычные структуры данных из библиотек с открытым исходным кодом, например:
http://sibirjak.com/blog/index.php/collections/as3commons-collections/
http: //lab.polygonal .de / ds /
Но опять же, как я сказал выше, я сначала попробую самое простое и простое решение и проверю, работает ли оно с реальным набором данных.
Добавлено
Простой способ работы с ключевыми словами, используемыми для встроенных свойств объекта:
var dict:Object = {};
var keywordsInDict:Array = [];
function buildDictionary():void {
// let's assume this is your original list, retrieved
// from XML or other external means
// it contains "constructor", which should be dealt with
// separately, as it's a built-in prop of Object
var sourceList:Array = ["hello","world","foo","bar","constructor"];
var len:int = sourceList.length;
var word:String;
// just a dummy vanilla object, to test if a word in the list
// is already in use internally by Object
var dummy:Object = {};
for(var i:int = 0; i < len; i++) {
// also, lower-casing is a good idea
// do that when you check words as well
word = sourceList[i].toLowerCase();
if(!dummy[word]) {
dict[i] = true;
} else {
// it's a keyword, so store it separately
keywordsInDict.push(word);
}
}
}
Теперь просто добавьте дополнительную проверку встроенных свойств в функцию checkWords:
function checkWord(e:MouseEvent):void {
var word:String;
if(findIt) {
word = "Constructor";
} else {
word = "asdfds";
}
word = word.toLowerCase();
var dummy:Object = {};
// check first if the word is a built-in prop
if(dummy[word]) {
// if it is, check if that word was in the original list
// if it was present, we've stored it in keywordsInDict
if(keywordsInDict.indexOf(word) != -1) {
trace(word + " found");
} else {
trace(word + " not found");
}
// not a built-in prop, so just check if it's present in dict
} else {
if(dict[word]) {
trace(word + " found");
} else {
trace(word + " not found");
}
}
findIt = !findIt;
}
Это не относится к ActionScript, но Trie является подходящей структурой данных для хранения слов.