当前位置: 首页 > 知识库问答 >
问题:

javascript - 在JS中,如何保证数组插入时的唯一性?

萧辰沛
2024-10-21

在JS中,如何保证数组插入时的唯一性?
比如说:

let list = [{id:1},{id:2},{id:10}]

function insert(id) {
    if (!list.some(item => { return item.item == id })) {
        // 判断和插入不是原子性的,会不会有并发问题?
        list.push({id:id})
    }
}

这样插入的时候会不会产生并发问题?非前端出身,不是很懂JS

我能想到的解决方案

插入一个临时数组,然后有一个统一的死循环将临时数组的数据插入数组中

共有6个答案

柴坚诚
2024-10-21

使用 Set:

let list = [{id: 1}, {id: 2}, {id: 10}];
let idSet = new Set(list.map(item => item.id));

function insert(id) {
    if (!idSet.has(id)) {
        list.push({id: id});
        idSet.add(id);
    }
}

使用 Map:

let list = [{id: 1}, {id: 2}, {id: 10}];
let idMap = new Map(list.map(item => [item.id, item]));

function insert(id) {
    if (!idMap.has(id)) {
        let newItem = {id: id};
        list.push(newItem);
        idMap.set(id, newItem);
    }
}

这两种方法都确保了插入时的唯一性,并避免了并发问题。

周飞
2024-10-21

JS没有线程安全问题

江丰羽
2024-10-21
  1. JS不会有并发问题,JS只有一个主线程,并使用宏任务和微任务的形式抢占这个线程,所以不会存在两个线程同时操作一个变量的情况。
  2. 如果要判断数组内是否存在再加入数据,应该使用Set或Map对象,而不是Array。因为Array需要每次遍历,Set或Map可以直接判断是否重复,也可以无需判断直接添加(add方法已经判断了重复)。

你要改的话一开始就要把你的list换成map,代码例子:

const idDataMap = new Map([{id: 1}, {id: 2}, {id: 10}].map(e=>[e.id, e]))

// 然后添加的时候直接加就好了,不需要再判断了
// 其实并不需要写这个函数,没必要
function appendData(newItem){
    idDataMap.set(newItem.id, newItem);
}

因为Map的key会储存为hash,后续会根据特征直接取数据,不需要遍历。Map在常用的数据结构里是性能最好的,简单来看,不管多大的数据取出来复杂度都是O(1),也就是一次操作就可以找到目标,不管数据多大。不过为了生成Map肯定在最开始是要遍历一次的,这一次遍历后,后续就随便用不需要担心性能了。

越狐若
2024-10-21

不会,js是单线程的。
所以如果有重复操作会被你的 !list.some(item => { return item.item == id }) 拦截掉。

小牛23068
2024-10-21

不用考虑,js 是单线程的

张丰
2024-10-21

在JavaScript中,如果您正在处理单线程环境(如浏览器中的JavaScript或Node.js的默认模式),那么您提到的并发问题实际上是不存在的,因为JavaScript是单线程的。但是,如果您的代码在某种形式的多线程环境(如Web Workers或Node.js的Cluster模块)中运行,或者如果您的数组操作被异步事件(如定时器、网络请求回调等)打断,那么确实可能会出现问题。

对于单线程环境,您的代码中有一个小错误需要修正:在some方法的回调函数中,您应该直接比较item.idid,而不是item.item。下面是修正后的代码:

let list = [{id:1},{id:2},{id:10}];

function insert(id) {
    // 使用正确的属性名进行比较
    if (!list.some(item => item.id === id)) {
        list.push({id: id});
    }
}

对于多线程环境或异步操作,确实需要采取额外的措施来确保数组的唯一性。但是,在大多数情况下,JavaScript运行在单线程环境中,所以直接的比较和插入就足够了。

如果您确实担心在多线程环境中或者在异步操作中保持数据的一致性,您可能需要考虑使用其他机制,比如:

  1. 锁(Locks):在多线程环境中,可以使用锁来同步对共享资源的访问。但请注意,JavaScript的标准库中没有内置的锁机制,您可能需要使用第三方库或在Node.js中使用特定的模块(如async_hooksworker_threads)。
  2. 使用Set或其他数据结构:如果您只是需要存储唯一的标识符,而不是整个对象,那么使用Set可能是一个更简单的选择。但是,如果您需要存储对象并基于对象的某个属性来保持唯一性,那么您可能需要自己实现这种逻辑。
  3. 使用数据库:如果您的应用程序需要处理大量数据或需要更高级的数据一致性保证,那么使用数据库(如MongoDB、PostgreSQL等)可能是更好的选择。数据库通常提供了事务处理、锁和其他机制来确保数据的一致性和完整性。
  4. 原子操作:在某些情况下,您可能需要实现自定义的原子操作来确保多个操作要么全部成功,要么全部失败。这通常涉及到更复杂的编程模式和同步机制。

对于大多数前端和许多Node.js应用程序来说,简单的单线程检查和插入就足够了。如果您确实需要处理并发或异步情况,请根据您的具体需求和环境选择适当的解决方案。

 类似资料:
  • 比如我在一个js文件中 怎么保证 按A-B—C 的顺序引入? 一定要按script标签那样动态引入吗?比如,import这种引入有什么好方法吗?

  • 1、主键约束 主键列上没有任何两行具有相同值(即重复值),不允许空(NULL); 2、唯一性约束 保证一个字段或者一组字段里的数据都与表中其它行的对应数据不同。和主键约束不同,唯一性约束允许为null,但是只能有一行; 3、唯一性索引 不允许具有索引值相同的行,从而禁止重复的索引和键值; 4、三者的区别 约束是用来检查数据的正确性; 索引是用来优化查询的; 创建唯一性约束会创建一个约束和一个唯一性

  • 问题内容: 我有以下SQLite代码。如何在每行中插入自动生成的唯一ID? 问题答案: 您可以将其定义为自动递增列: 正如MichaelDorner指出的那样,SQLite文档说an可以做同样的事情,并且速度稍快。该类型的列是其别名,其行为类似于自动增量列。 此行为是隐式的,可能会使经验不足的SQLite开发人员措手不及。

  • 我有一个对象数组,如何在TypeScript/JavaScript中筛选唯一id数组 列表数组-

  • 我试图在Android上开发一个人脸识别应用程序,我使用JavaCV+OpenCV 2.4.2来使用Philipp Wagner的人脸识别类。 该类有一个Train方法,它接受Mat和Integer数组作为输入(在C++中): JavaCV接受'train'方法的属性为,这里是我的难点! 我在向CVARR加载数据时遇到了一点麻烦...我已经有了作为数据字符串的标签...但我似乎找不到将这些标签作为

  • 问题内容: 如何获得数组中唯一值的列表?我是否总是必须使用第二个数组,或者是否有类似于JavaScript中Java哈希表的东西? 我将仅使用 JavaScript 和 jQuery 。不能使用其他库。 问题答案: 由于我在@Rocket答案的注释中继续进行了讨论,因此我不妨提供一个不使用任何库的示例。这需要两个新的原型函数,并且 为了提高可靠性,可以用MDN的垫片代替,并检查每个元素的值是否等于

  • 如下,有什么办法在编辑器层面(比如vscode)保证代码安全么? 人总是会粗心大意的,if(1 == value)写起来也不符合直觉…… 或者有一些小技巧讨论一下也行。 TS伪代码如下

  • 假设我有以下对象数组 现在我想收集具有唯一对象(匹配和)的数组,即。 我能收集所有的东西 但不知道如何过滤掉重复的。有什么建议吗? 编辑:两个不同数组上的我的对象不相同。至少基于属性的数量。