У меня есть массив объектов. Каждый объект имеет свойство, названное именем. Я хочу эффективно удалить объект с конкретным именем от массива. Действительно ли это - Лучший способ?
private function RemoveSpoke(Name:String):void {
var Temp:Array=new Array;
for each (var S:Object in Spokes) {
if (S.Name!=Name) {
Temp.push(S);
}
}
Spokes=Temp;
}
Если вы готовы потратить немного памяти на таблицу поиска, это будет довольно быстро:
private function remove( data:Array, objectTable:Object, name:String):void {
var index:int = data.indexOf( objectTable[name] );
objectTable[name] = null;
data.splice( index, 1 );
}
Тест для этого выглядит так:
private function test():void{
var lookup:Object = {};
var Spokes:Array = [];
for ( var i:int = 0; i < 1000; i++ )
{
var obj:Object = { name: (Math.random()*0xffffff).toString(16), someOtherProperty:"blah" };
if ( lookup[ obj.name ] == null )
{
lookup[ obj.name ] = obj;
Spokes.push( obj );
}
}
var t:int = getTimer();
for ( var i:int = 0; i < 500; i++ )
{
var test:Object = Spokes[int(Math.random()*Spokes.length)];
remove(Spokes,lookup,test.name)
}
trace( getTimer() - t );
}
У меня нет данных для его резервного копирования, но я предполагаю, что array.filter может быть самым быстрым.
Вы также можете использовать ArrayCollection с filterFunction, чтобы получить представление о том же объекте Array
Самый быстрый способ будет следующим:
function remove(array: Array, name: String): void {
var n: int = array.length
while(--n > -1) {
if(name == array[n].name) {
array.splice(n, 1)
return
}
}
}
remove([{name: "hi"}], "hi")
Вы также можете удалить оператор return, если хотите избавиться от всех элементов, соответствующих данному предикату.
Если вы не против использовать ArrayCollection, который является оберткой для класса Array, вы можете сделать что-то вроде этого:
private function RemoveSpoke(Name:String, Spokes:Array):Array{
var ac:ArrayCollection = new ArrayCollection(Spokes);
for (var i:int=0, imax:int=ac.length; i<imax; i++) {
if (Spokes[i].hasOwnProperty("Name") && Spokes[i].Name === Name) {
ac.removeItemAt(i);
return ac.source;
}
}
return ac.source;
}
Возможно, этот метод (оптимизированный метод сращивания CJ's) еще больше улучшит метод, предложенный Квазимондо:
http://cjcat.blogspot.com/ 2010/05/stardust-v11-with-fast-array-splicing_21.html
В общем случае вы должны предпочесть старый цикл for-loop, а не "for each" и "for each in", и использовать Vector, если ваши элементы имеют одинаковый тип. Если производительность действительно важна, вам следует рассмотреть возможность использования связного списка.
Посмотрите слайды Гранта Скиннера http://gskinner.com/talks/quick/ и блог Джексона Данстана для получения дополнительной информации об оптимизации.
Вот эффективная с точки зрения повторного использования функция, позволяющая делать больше, чем удаление элемента. Она возвращает индекс или -1, если элемент не найден.
function searchByProp(arr:Array, prop:String, value:Object): int { var item:Object; var n: int = arr.length; for(var i:int=n;i>0;i--) { item = arr[i-1]; if(item.hasOwnProperty(prop)) if( value == item[prop] ) return i-1; } return -1; }