我想删除数组中所有可能重复的值。目前,我在while循环中使用remove(x:T):Bool
函数,但我想知道表达式部分。
我已经开始使用:
function removeAll(array:Array<String>, element:String):Void
while (array.remove(element)) {}
但是我想知道这些行是否会更有效:
while (array.remove(element)) continue;
while (array.remove(element)) true;
while (array.remove(element)) 0;
或者是否有任何区别。
我猜测使用continue
的效率较低,因为它实际上必须做某事,true
和0
的效率稍高,但仍然可以做些事,而{{1 }}可能是最有效的。
有人对此有任何背景信息吗?
答案 0 :(得分:2)
没有任何区别。实际上,对于{}
,0
和false
情况,生成的代码甚至没有任何区别:它们最终都至少在JS目标上生成{}
但是,如果您的大型数组包含许多重复项,则可能会遇到问题:在这种情况下,remove()
将被调用多次,并且每次都必须遍历该数组(直到找到一个匹配)。在这种情况下,使用filter()
可能更有效:
function removeAll(array:Array<String>, element:String):Array<String>
return array.filter(function(e) return e != element);
就个人而言,我还发现它比空着身体的while
循环要优雅一些。但同样,这取决于用例:这确实会创建一个新数组,从而导致分配。通常,这不必担心,但是例如,如果您在游戏的更新循环中进行操作,则可能要避免使用它。
答案 1 :(得分:2)
虽然其他建议使用filter
,但它会创建一个新的列表/数组实例,这可能会导致您的其他代码失去引用。
如果循环array.remove
,它将每次循环遍历数组前面的所有元素,而效果不那么好。
IMO更好的方法是使用反向while
循环:
var i = array.length;
while(--i >= 0)
if(array[i] == element) array.splice(i, 1);
答案 2 :(得分:1)
就while
循环的表达式部分而言,似乎在编译时只是将其设置为空括号({}
),所以您所做的实际上并不重要。
就性能而言,更好的解决方案是以下方法2:
class Test
{
static function main()
{
var thing:Array<String> = new Array<String>();
for (index in 0...1000)
{
thing.push("0");
thing.push("1");
}
var copy1 = thing.copy();
var copy2 = thing.copy();
trace("epoch");
while (copy1.remove("0")) {}
trace("check");
// Method 2.
copy2 = [
for (item in Lambda.filter(copy2, function(v)
{return v != "0";}))
item
];
trace("check");
}
}
,可以在[here](https://try.haxe.org/#D0468“尝试Haxe示例。”)中看到。对于Array<String>
中的200,000个单字符元素,方法2花费0.017s,而方法1花费44.544s。
答案 3 :(得分:0)
对于大型数组,使用临时数组然后在填充后将其分配回(try中的method3)会更快一些?
OR
如果您不想使用临时文件,可以分配回来并进行拼接(try中的method4)?
在我设置vars时,两者在代码方面都更加冗长,但是在Mac上,运行时似乎更快,请参见我的method3方法摘要:
while( i < l ) { if( ( s = copy[ i++ ] ) != '0' ) arr[ j++ ] = s;
copy = arr;
我缺少针对这些方法的明显之处吗?