【发布时间】:2011-08-25 06:21:40
【问题描述】:
您好,我在 flash 中只有一个名称(字符串)数组,我想确保删除数组中的所有重复项,或者至少确保数组中每个重复出现的值只执行一次函数。
【问题讨论】:
标签: flash actionscript-3 actionscript
您好,我在 flash 中只有一个名称(字符串)数组,我想确保删除数组中的所有重复项,或者至少确保数组中每个重复出现的值只执行一次函数。
【问题讨论】:
标签: flash actionscript-3 actionscript
好答案!
我检查了其中一些,与我的相比,它们的结果更差。 示例:
const origin: Vector.<String> = Vector.<String>(["a", "c", "d", "c", "b", "a", "e", "b", "a"]);
function getUniqueVector(origin: Vector.<String>): Vector.<String> {
const n: uint = origin.length;
var res: Vector.<String> = new Vector.<String>();
var i: int = 0;
while(i < n) {
var el: String = origin[i];
if(res.indexOf(el) == -1) res.push(el);
i += 1;
}
return res;
}
trace(getUniqueVector(origin)); // unique elements vector
我的数据统计:
字典方法:8946ms、8718ms、8936ms
Obj 方法:8800ms、8809ms、8769ms
我的旧方法:8723ms、8599ms、8700ms
这种方法:6771ms、6867ms、6706ms
2019 年 7 月 2 日更新
值得注意的是,为了获得更好的性能,创建对象,并将每个推送的值设置为 O(1) 复杂度检索的关键,因此结果会更好一些。
但是 Flash 已经死了,而且可能是 ActionScript,所以这是一个葬礼演讲 :(
【讨论】:
function removeDuplicateElement(_arr:Array):Array{
//set new Dictionary
var lDic:Dictionary = new Dictionary();
for each(var thisElement:* in _arr){
//All values of duplicate entries will be overwritten
lDic[thisElement] = true;
}
_arr = [];
for(var lKey:* in lDic){
_arr.push(lKey);
}
return _arr;
}
【讨论】:
这是一种更优雅的删除重复项的方法:
var items:Vector.<String> = Vector.<String>(['tortoise', 'cat', 'dog', 'bunny', 'dog', 'cat', 'bunny', 'lion']);
var uniqueItems:Vector.<String> = items.filter(function(item:String, index:int, vector:Vector.<String>):Boolean {
return index==0?true:(vector.lastIndexOf(item, index-1) == -1);
});
数组的相同方法:
var items:Array = ['tortoise', 'cat', 'dog', 'bunny', 'dog', 'cat', 'bunny', 'lion'];
var uniqueItems:Array = items.filter(function(item:String, index:int, array:Array):Boolean {
return index==0?true:(array.lastIndexOf(item, index-1) == -1);
});
【讨论】:
这是一种方法,我相信还有其他方法。
function removeDuplicate(sourceArray:Array) : void
{
for (var i:int = 0; i < sourceArray.length - 1; i++)
{
for (var j:int = i + 1; j < sourceArray.length; j++)
{
if (sourceArray[i] === sourceArray[j])
{
// Remove duplicated element and decrease j index.
sourceArray.splice(j--, 1);
}
}
}
}
【讨论】:
我投票支持 Adam 的选项,但后来我发现了这一点,而且在我看来,这可能是更好的性能吗?
for (var i:uint = array.length; i > 0; i--){
if (array.indexOf(array[i-1]) != i-1){
array.splice(i-1,1);
}
}
这里的想法是你在数组中向后循环,并且由于 indexOf 为你提供了第一个出现的索引,你可以用当前的 index(i) 检查找到的索引,如果不一样就删除。
【讨论】:
如果 sourceArray[i] 与 sourceArray[j] 匹配不止一次,@prototypical 的响应会不会出现问题,因为如果一个元素被 .splice()d 从中取出,sourceArray 的长度会更短?
我已经重写了这个方法,从末尾开始计数,这样就不会发生这种情况
for (var i:int = sourceArray.length - 2; i >= 0; --i)
{
for (var j:int = sourceArray.length - 1; j > i; --j)
{
trace(i, j);
if (sourceArray[j] === sourceArray[i]) sourceArray.splice(j, 1);
}
}
【讨论】:
更多猫皮:
var a:Array = ["Tom", "John", "Susan", "Marie", "Tom", "John", "Tom", "Eva"];
a.sort();
var i:int = 0;
while(i < a.length) {
while(i < a.length+1 && a[i] == a[i+1]) {
a.splice(i, 1);
}
i++;
}
【讨论】:
很多方法。您可以对数组进行排序并对其进行迭代,而忽略与上一次迭代匹配的条目。或者您可以使用 indexOf() 搜索重复项。或者您可以遍历数组,构建一个以字符串为键的字典(并忽略已经有条目的键)。
这是字典方式,每个唯一条目的内存成本为 1 个布尔值,当您期望有很多欺骗时,内存成本很容易,而且速度很快。如果你的受骗者相对较少,那么对连续受骗者进行排序+剔除可能会更有效
import flash.utils.Dictionary;
var array:Array = ["harry","potter","ron","harry","snape","ginny","ron"];
var dict:Dictionary = new Dictionary();
for (var i:int = array.length-1; i>=0; --i)
{
var str:String = array[i] as String;
trace(str);
if (!dict[str])
{
dict[str] = true;
}
else
{
array.splice(i,1);
}
}
dict = null;
trace(array);
这是一种排序方式,但请注意:这不会保留顺序!你没有说这是否重要。但是因为它使用的是快速排序,所以它确实倾向于具有 O(N log N) 的性能以及额外的一次传递,除非您的数据当然是病态的情况。
var array:Array = ["harry","potter","ron","harry","ron","snape","ginny","ron"];
array.sort();
trace(array);
for (var i:int = array.length-1; i>0; --i)
{
if (array[i]===array[i-1])
{
array.splice(i,1);
}
}
trace(array);
除了没有说明顺序是否重要之外,您没有说明留下哪些欺骗是否重要:索引最低的那个,或者找到的最后一个。如果这很重要,您将需要重新排序我的字典示例以向相反方向运行。我从最后开始,因为这样可以在不使循环计数无效的情况下进行拼接(即通过在循环期间更改 array.length)如果顺序很重要,请按通常的正向循环并复制每个字符串的第一次出现到一个新数组,或者像这样修改循环计数器。这可能是我会使用的技术,因为它保留了顺序并保留了每个字符串的第一次遇到的实例:
import flash.utils.Dictionary;
var array:Array = ["harry","potter","ron","harry","snape","ginny","ron"];
var dict:Dictionary = new Dictionary();
var len:int = array.length;
for (var i:int = 0; i<len; ++i)
{
var str:String = array[i] as String;
if (!dict[str])
{
dict[str] = true;
}
else
{
array.splice(i,1);
i--; len--;
}
}
dict = null;
trace(array);
【讨论】:
这是另一种方法,可能看起来更好看:
var removeList:Array = [];
// loop over every item in the original array
for each (var item:* in array) {
// loop over every item again, checking for duplicates
for each (var other:* in array) {
// if two items that aren't the same item are equal and `other` doesn't
// exist in the remove list, then cache it for later removal.
if (item == other && item !== other && removeList.indexOf(other) == -1)
removeList.push(other);
}
}
// next, loop over the cached remove list and remove 'selected' items for removal
for each (var remove:* in removeList)
array.splice(array.indexOf(remove), 1);
这可能不是最高效的方法,@prototypical 的方法可能效率更高,但这是您要求的理论:)
【讨论】: