给定一个Map,赋值,检查Dart中是否包含任何重复值的最快方法是什么?我目前正在使用一个由Map的值组成的Set,并根据原始Map检查它的长度,当然这是有效的,但我想知道是否有一个特别高效的替代方案。
Set d = new Set.from(assignment.values);
if (d.length < assignment.length) {
return false; // indicates has duplicates in this context
}
编辑: 尝试@ mezoni的解决方案为我的程序修改,但它实际上比我原来的版本慢了一点。它可能与其他任何事情有关。
List values = new List.from(assignment.values);
Set set = new Set();
for (var i = 0; i < assignment.length; i++) {
if (!set.add(values[i])) {
return false;
}
}
答案 0 :(得分:3)
复杂性明智,你将无法获得更快的速度。创建集合并使用Map的值填充它是元素数量的线性。显然,你必须贯穿所有的价值观,所以你不能做得更好。
也许你可以找到一个具有较小常数因子的解决方案,但目前尚不清楚。特别是对于较大的集合,我认为Set解决方案非常有效。
答案 1 :(得分:2)
这是一个算法问题,而不是Dart问题。无论如何,您必须检查每个值与其他值,检查n-1 + n-2 + ... + n-(n-1)
或n^2/2
。以编程方式,创建一个集合很容易,但您也可以生成一个数组,对数组进行排序,然后迭代一次以检查重复项。以O(n log n)结束。
答案 2 :(得分:1)
Fastets方式(如果你真的需要更好的表现):
void main() {
// Values from map
var values = [1,2,3,2,1,3,2,1];
var length = values.length;
var set = new Set();
var duplicate = false;
// Only for statistics purpose
var statistics = 0;
for(var i = 0; i < length; i++) {
statistics++;
if(!set.add(values[i])) {
duplicate = true;
break;
}
}
print("Duplicate: $duplicate");
print("Performed in ${statistics} iteration(s) from $length possible");
}
输出:
Duplicate: true
Performed in 4 iteration(s) from 8 possible
P.S。
可以建议将第一个示例与List
值一起使用。
但由于Map.values
不是List
而是Iterable
,因此效率更高,不要将它们转换为List
,而是按原样使用。
以下是用于Iterable
个对象的修改示例。
它会更快地工作,因为在这个算法中不需要将所有值都转换为List
对象,因为它不希望无例外地使用所有元素。
相反,它希望尽可能少地使用原始源上的访问操作。如果源支持对值的访问的延迟操作(如Iterable
),那将更好。
void main() {
// Values from map
var values = [1,2,3,2,1,3,2,1];
var assignment = {};
var length = values.length;
var key = 0;
for(var value in values) {
assignment[key++] = value;
}
var set = new Set();
var duplicate = false;
// Only for statistics purpose
var statistics = 0;
for(var value in assignment.values) {
statistics++;
if(!set.add(value)) {
duplicate = true;
break;
}
}
print("Duplicate: $duplicate");
print("Performed in ${statistics} iteration(s) from $length possible");
}