检查Javascript对象数组中是否存在对象值,如果不存在,则向数组添加一个新对象。

283

如果我有以下的对象数组:

[ { id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 2, username: 'ted' } ]

有没有一种方法可以遍历数组,检查特定的用户名值是否已经存在,如果存在,则什么也不做,但如果不存在,则添加一个带有该用户名(和新ID)的新对象到数组中?

谢谢!


1
比尔和泰德应该有相同的ID吗? - user2357112
为什么有两个具有相同 id 的元素?这个数组中的元素是否可能被移除,或者我们可以确定新元素的 id 总是等于 arr.length + 1 吗? - raina77ow
如果您不想使用循环,请查看这个 Q&A 来扩展数组原型,https://dev59.com/YXI-5IYBdhLWcg3wKVA9。 - Cem Özer
本地函数与普通循环相比较慢,而且它们的支持仅限于某些浏览器版本。请检查下面的答案。 - Zaheen
这是一个基本上错误的问题,因为你可以通过避免使用数组来实现。 - Bekim Bacaj
@user2576960 当你有时间时,请检查我的解决方案,因为它通过一个简单的一行函数来简洁地实现了这个目标。我提供了几种不同的方法来实现这个目标,但我觉得我的**#1#2**解决方案最符合你的要求。 - Brandon McConnell
22个回答

419

我假设这里的id是唯一的。 some 是一个用于检查数组中是否存在某些东西的很棒的函数:

const arr = [{ id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 3, username: 'ted' }];

function add(arr, name) {
  const { length } = arr;
  const id = length + 1;
  const found = arr.some(el => el.username === name);
  if (!found) arr.push({ id, username: name });
  return arr;
}

console.log(add(arr, 'ted'));


2
谢谢Andy,这是一个非常干净的解决方案,而且运行得非常好。我以前没有遇到过这个方法。你的假设是正确的,我的ID示例只是一个打字错误,我使用arr.length + 1来确定ID。 - user2576960
3
请注意,IE8及更早版本不支持该函数。 - BetaRide
3
当然可以:if (arr.some(function (el) { return el.Id == someId; })) { // do something }。别忘了加上 return,否则你将得不到任何返回值。 - Andy
1
嗨,如果我找到了值,我怎么访问id? - Kusal Kithmal
1
非常好的解决方案,正是我所需要的。谢谢! - z0mbieKale
显示剩余6条评论

73

这个小片段对我很有用...

const arrayOfObject = [{ id: 1, name: 'john' }, {id: 2, name: 'max'}];

const checkUsername = obj => obj.name === 'max';

console.log(arrayOfObject.some(checkUsername))

如果您有像['john','marsh']这样的元素数组,那么我们可以做如下操作

const checkUsername = element => element == 'john';
    
console.log(arrayOfObject.some(checkUsername))

3
相当优雅的方法!更多关于使用.some的详细信息和示例,请访问此处 - https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/some - James Marino

49

检查现有用户名相当简单:

var arr = [{ id: 1, username: 'fred' }, 
  { id: 2, username: 'bill'}, 
  { id: 3, username: 'ted' }];

function userExists(username) {
  return arr.some(function(el) {
    return el.username === username;
  }); 
}

console.log(userExists('fred')); // true
console.log(userExists('bred')); // false

但是当你需要向这个数组添加新用户时,该怎么做并不那么明显。最简单的方法就是将一个id等于array.length+1的新元素推入数组中:

function addUser(username) {
  if (userExists(username)) {
    return false; 
  }
  arr.push({ id: arr.length + 1, username: username });
  return true;
}

addUser('fred'); // false
addUser('bred'); // true, user `bred` added

这将确保ID的唯一性,但如果从末尾移除了某些元素,则会使数组看起来有点奇怪。


谢谢这个。最终我选择了Andy的解决方案,因为它更简洁地实现了同样的功能。我不会在任何时候删除用户,所以ID应该保持一致。这个检查允许用户登录、退出和重新登录,而不会随着时间的推移而增加数组。只是为了提供信息,我正在与passport.js一起使用这个函数,我没有找到一种在不修改passport代码的情况下从数组中删除用户的方法。这个解决方案很好地解决了问题。 - user2576960

27

检查一个数组中是否存在一个元素(在你的情况下是对象)可能有多种可能的方法


const arr = [
  { id: 1, username: 'fred' },
  { id: 2, username: 'bill' },
  { id: 3, username: 'ted' },
];

假设你想查找id = 3的对象。

1. find:它在数组中搜索元素,如果找到则返回该元素,否则返回undefined。它返回提供的数组中满足所提供测试函数的第一个元素的值。 参考

const ObjIdToFind = 5;
const isObjectPresent = arr.find((o) => o.id === ObjIdToFind);
if (!isObjectPresent) {            // As find return object else undefined
  arr.push({ id: arr.length + 1, username: 'Lorem ipsum' });
}

2. filter: 它在数组中搜索元素并过滤出所有符合条件的元素。它返回一个新的数组,其中包含所有的元素,如果没有元素符合条件,则返回一个空数组。参考资料

const ObjIdToFind = 5;
const arrayWithFilterObjects= arr.filter((o) => o.id === ObjIdToFind);
if (!arrayWithFilterObjects.length) {       // As filter return new array
  arr.push({ id: arr.length + 1, username: 'Lorem ipsum' });
}

3. some: some() 方法测试通过提供的函数实现的条件的至少一个数组元素是否存在。它返回一个布尔值。 参考文献

const ObjIdToFind = 5;
const isElementPresent = arr.some((o) => o.id === ObjIdToFind);
if (!isElementPresent) {                  // As some return Boolean value
  arr.push({ id: arr.length + 1, username: 'Lorem ipsum' });
}

1
从 Python 转来,我很惊讶地发现没有人关心效率。第一个解决方案使用 find 看起来更好,因为迭代会在找到第一个匹配元素时停止,或者使用带有 break 的 for 循环。 - Uneconscience UneSource

21

这是除了@sagar-gavhane的回答之外我所做的事情

const newUser = {_id: 4, name: 'Adam'}
const users = [{_id: 1, name: 'Fred'}, {_id: 2, name: 'Ted'}, {_id: 3, name:'Bill'}]

const userExists = users.some(user => user.name === newUser.name);
if(userExists) {
    return new Error({error:'User exists'})
}
users.push(newUser)

1
嗨,如果我找到了值,我怎样才能访问该ID? - Kusal Kithmal
做这个非常简单...if (userExists) { const userId = userExists.id return userId; }... - Michael Enitan

17

我认为这是解决这个问题的最短路径。在这里,我使用了ES6箭头函数和“ .filter”来检查新增用户名的存在。

var arr = [{
    id: 1,
    username: 'fred'
}, {
    id: 2,
    username: 'bill'
}, {
    id: 3,
    username: 'ted'
}];

function add(name) {
    var id = arr.length + 1;        
            if (arr.filter(item=> item.username == name).length == 0){
            arr.push({ id: id, username: name });
        }
}

add('ted');
console.log(arr);

Fiddle链接


9
假设我们有一个对象数组,你想检查像这样定义的名称的值:
let persons = [ {"name" : "test1"},{"name": "test2"}];

if(persons.some(person => person.name == 'test1')) {
    ... here your code in case person.name is defined and available
}

请添加几句话来解释你的代码正在做什么,这样你就可以获得更多的赞同票。 - Fuzzy Analysis
如果我想比较具有2个属性的对象,例如 {"name" : "test1", "age": 30},该怎么办? - probitaille

3

试试这个

首先使用一些方法

  let arr = [{ id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 3, username: 'ted' }];
    let found = arr.some(ele => ele.username === 'bill');
    console.log(found)

第二种方法:使用 includes 和 map

   let arr = [{ id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 3, username: 'ted' }];
    let mapped = arr.map(ele => ele.username);
    let found = mapped.includes('bill');
    console.log(found)

如果我想比较具有两个属性的对象,例如{"name" : "test1", "age": 30},该怎么办? - probitaille
@probitaille 你可以使用 && 运算符 const obj = {"name": "test1", "age": 30}; arr.some(a => a.name === obj.name && a.age === obj.age); - Kamran

2
您可以通过原型来使您的数组更加模块化,尝试像这样做:

您可以通过原型来使您的数组更加模块化,尝试像这样做:

    Array.prototype.hasElement = function(element) {
        var i;
        for (i = 0; i < this.length; i++) {
            if (this[i] === element) {
                return i; //Returns element position, so it exists
            }
        }

        return -1; //The element isn't in your array
    };

您可以将其用作:

 yourArray.hasElement(yourArrayElement)

2

接受的答案也可以使用箭头函数在.some上以以下方式编写

 function checkAndAdd(name) {
     var id = arr.length + 1;
     var found = arr.some((el) => {
           return el.username === name;
     });
     if (!found) { arr.push({ id: id, username: name }); }
 }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接