我的答案是肯定的,如果您同意在删除后的下一次迭代中继续使用 Set 中的下一个值。在迭代过程中,您当前在哪个 Set 实例上似乎并不重要。非常理想!
这是我的测试代码:
s = new Set([ { a: 0 }, { a: 1 }, { a: 2 }, { a: 3 } ]);
do {
for (let x of s) {
console.log(x.a);
if (Math.random() < 0.2) {
console.log('deleted ' + x.a);
s.delete(x);
}
}
} while (s.size > 0);
在 Firefox 75.0 中,它工作得很好。集合应该保持它们的插入顺序,并且确实如此,它在迭代时按该顺序打印出来。无论删除什么,它都会按照插入顺序继续:
0
1
2
3
0
1
deleted 1
2
3
0
2
deleted 2
3
0
3
0
deleted 0
3
3
...
3
3
deleted 3
我也使用类似的代码进行了测试,但没有使用迭代过程的当前实例:
sCopy = [{ a: 0 }, { a: 1 }, { a: 2 }, { a: 3 }];
s = new Set(sCopy);
do {
for (let x of s) {
console.log(x.a);
if (Math.random() < 0.2) {
let deleteMe = Math.floor(Math.random() * s.size);
console.log('deleted ' + sCopy[deleteMe].a);
s.delete(sCopy[deleteMe]);
sCopy.splice(deleteMe, 1);
}
}
} while (s.size > 0);
我不得不使用相邻数组,因为无法查找 Set 的随机索引来删除随机实例。所以我只是从数组中创建了 Set,所以它使用相同的对象实例。
效果也很好,如您所见:
0
deleted 1
2
deleted 2
3
0
3
0
deleted 0
3
3
3
3
deleted 3
是的...我什至还测试了随机对象实例插入...同样的交易,这次我不会发布输出:
sCopy = [{ a: 0 }, { a: 1 }, { a: 2 } ];
s = new Set(sCopy);
do {
for (let x of s) {
console.log(x.a);
if (Math.random() < 0.1) {
let newInstance = { a: Math.random() * 100 + 100 };
console.log('added ' + newInstance.a);
s.add(newInstance);
sCopy.push(newInstance);
}
if (Math.random() < 0.2) {
let deleteMe = Math.floor(Math.random() * s.size);
console.log('deleted ' + sCopy[deleteMe].a);
s.delete(sCopy[deleteMe]);
sCopy.splice(deleteMe, 1);
}
}
} while (s.size > 0);