2010-05-26 45 views
6

Tôi có một mảng đối tượng. Mỗi đối tượng có một thuộc tính được gọi là tên. Tôi muốn loại bỏ một đối tượng một cách hiệu quả với một tên cụ thể từ mảng đó. Đây có phải là cách tốt nhất?Cách hiệu quả hơn để xóa phần tử khỏi mảng trong Actionscript 3

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; 
    } 

Trả lời

12

Nếu bạn sẵn sàng chi một số bộ nhớ trên một bảng tra cứu này sẽ là khá nhanh:

private function remove(data:Array, objectTable:Object, name:String):void { 
var index:int = data.indexOf(objectTable[name]); 
objectTable[name] = null; 
data.splice(index, 1); 
} 

các thử nghiệm cho điều này có vẻ như thế này:

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); 

}

+0

Một điều quan trọng về giải pháp này: nó sẽ chỉ hoạt động nếu mỗi "tên" là duy nhất. Nếu có nhiều đối tượng có cùng tên thì bảng tra cứu sẽ thất bại, ít nhất nếu nó được xây dựng như thế này. – Quasimondo

+0

thú vị ... vì vậy về cơ bản bạn có hai danh sách với dữ liệu trùng lặp ... nói chung sẽ tốt hơn nếu chỉ sử dụng bảng tra cứu và phân phối với mảng cho các tình huống này? thực hiện điều này chỉ vì đối tượng có thuộc tính 'name' hoặc' indexOf' tìm kiếm trong mọi giá trị thuộc tính của đối tượng? – mga

+0

Có, nếu bạn không cần mảng cho các mục đích khác (như phân loại hoặc truy cập các phần tử theo chỉ số) trong trường hợp này bạn chỉ có thể sử dụng bảng tra cứu. indexOf tìm các phiên bản của đối tượng. Trong trường hợp này, nó không sử dụng "tên" ở tất cả để so sánh. Tên được sử dụng làm băm trong bảng tra cứu. – Quasimondo

0

Nếu bạn không nhớ bằng cách sử dụng ArrayCollection, mà là một wrapper cho lớp Array, bạn có thể làm một cái gì đó như thế này:

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; 
} 
+0

FYI ArrayCollection chỉ khả dụng trong Flex – Quasimondo

+1

@Quasimondo: FYI Flex là một trong các thẻ về câu hỏi. – Robusto

+0

Oh đúng, tôi hoàn toàn bỏ lỡ một. – Quasimondo

1

tôi không có dữ liệu để sao lưu nó lên nhưng tôi đoán là array.filter có thể là nhanh nhất.

+1

Nếu bạn muốn nói điều gì đó như sau: var filterName: String = "something"; Spokes = Spokes.filter (function (element: *, index: int, arr: Array): Boolean { \t return (element.name! = FilterName);}); sau đó tôi phải làm bạn thất vọng. Đó là khoảng 5x chậm hơn so với Joa và gần như 30x chậm hơn của tôi. – Quasimondo

+0

Haha. Các bạn ăn gian! ;) Là array.filter ít nhất là nhanh nhất cho các vòng lặp/iterator dựa trên phương pháp? –

5

Cách nhanh nhất sẽ là thế này:

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") 

Bạn cũng có thể loại bỏ các tuyên bố trở lại nếu bạn muốn thoát khỏi tất cả alements phù hợp với vị ngữ nhất định.

+0

Joa! Bạn đá. Nhưng Apparat sẽ có thể làm cho nó nhanh hơn?:) –

+7

Tôi cho phép bản thân mình so sánh "nhanh nhất" với tôi và có tin xấu: xóa 500 phần tử khỏi mảng 1000 phần tử - của bạn 34 ms, của tôi 4ms ;-) – Quasimondo

0

Bạn cũng có thể sử dụng ArrayCollection với một filterFunction để có được một cái nhìn vào đối tượng Array cùng

0

Anh re là một chức năng hiệu quả về khả năng sử dụng lại, cho phép bạn làm nhiều hơn loại bỏ phần tử. Nó trả về chỉ mục, hoặc -1 nếu không tìm thấy.

 
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; 
} 
+0

Dường như định dạng đã xóa loại vectơ của bạn, nhưng tôi đoán đó là "Đối tượng". Tôi đã thử nghiệm nó một cách nhanh chóng và ít nhất là đối với tôi bằng cách sử dụng Vector trong trường hợp này là thực sự chậm hơn. Tôi nghĩ nếu bạn muốn lợi nhuận từ tốc độ của Vector bạn cũng nên sử dụng một loại thực và không phải "Object". – Quasimondo

+0

Cảm ơn Quasi. Bạn đã thử nghiệm bằng cách sử dụng chức năng của tôi? Nó có thêm điều kiện (hasOwnProperty) sẽ làm chậm nó nhưng có ý nghĩa nếu bạn không chắc chắn đối tượng sẽ có thuộc tính. Để làm cho nó nhanh hơn loại bỏ điều đó. Nhưng người dùng hỏi về hiệu quả, và chức năng này nói đến điều đó về khả năng sử dụng lại. – reelfernandes

+0

Tôi đã thử nghiệm nó với đề xuất của Joa, do đó hasOwnProperty không phải là vấn đề ở đây. – Quasimondo

1

Nói chung bạn nên thích cái cũ cho vòng qua "cho mỗi" và "cho mỗi" và sử dụng Vector nếu các phần tử của bạn có cùng loại. Nếu hiệu suất thực sự quan trọng, bạn nên cân nhắc sử dụng danh sách được liên kết.

Xem trang trình bày của Grant Skinners http://gskinner.com/talks/quick/ và Blog của Jackson Dunstan để biết thêm thông tin về tối ưu hóa.

10

myArray.splice (myArray.indexOf (myInstance), 1);

Các vấn đề liên quan