【问题标题】:Check if object value exists within a Javascript array of objects and if not add a new object to array检查对象值是否存在于 Javascript 对象数组中,如果不存在则将新对象添加到数组
【发布时间】:2014-05-15 16:34:24
【问题描述】:

如果我有以下对象数组:

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

有没有办法循环遍历数组来检查特定的用户名值是否已经存在,如果它什么都不做,但是如果它没有用所述用户名(和新 ID)向数组中添加一个新对象?

谢谢!

【问题讨论】:

  • Bill 和 Ted 是否应该具有相同的 ID?
  • 为什么有两个元素具有相同的id?是否有可能从这个数组中删除元素,或者我们可以确定新元素的id 总是等于arr.length + 1
  • 如果您不想循环遍历它,请查看此问答以扩展数组原型,stackoverflow.com/questions/1988349/…
  • 与普通循环相比,本机函数速度较慢,并且它们的支持仅限于某些浏览器版本。在下面检查我的答案。
  • 这是一个根本错误的问题,因为您可以通过避免使用数组来做到这一点。

标签: javascript arrays object for-loop foreach


【解决方案1】:

我假设ids 在这里是独一无二的。 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'));

【讨论】:

  • 感谢安迪,这是一个非常干净的问题解决方案,并且运行良好。我以前没有遇到过一些方法。您的假设是正确的,我的 ID 示例只是一个错字,我使用 arr.length + 1 来确定 ID。
  • 注意IE8及更早版本不支持某些功能。
  • 找到的函数可以做成IF吗?类似于: if (arr.some(function (el) { el.Id == someId) 如果存在或不存在,它将返回 true 或 false?
  • @stibay, some 确实返回一个布尔值。 found 将是 truefalse,具体取决于是否满足回调中的条件。
  • 哦,当然:if (arr.some(function (el) { return el.Id == someId; })) { // do something }。不要忘记return,否则您将一无所获。
【解决方案2】:

这个小sn-ps对我有用..

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】:

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

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 的唯一性,但是如果将一些元素从它的末尾取出,会使这个数组看起来有点奇怪。

【讨论】:

  • 谢谢。我最终选择了安迪的解决方案,因为它是实现相同目标的更简洁的方式。我不会在任何时候删除用户,所以 ID 应该保持一致。该检查允许用户登录、退出和重新登录,而无需阵列超时。仅供参考,我将此功能与 passport.js 结合使用,并且我无法找到一种在不使用护照代码本身的情况下从数组中删除用户的方法。这个解决方案效果很好。
【解决方案4】:

这是我除了@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)

【讨论】:

  • 嗨,如果我找到了值,我该如何访问 id?
  • 这样做真的很简单...if(userExists) { const userId = userExists.id return userId; }...
【解决方案5】:

我认为,这是解决此问题的最短方法。这里我使用了 .filter 的 ES6 箭头函数来检查是否存在新添加的用户名。

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);

Link to Fiddle

【讨论】:

    【解决方案6】:

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

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

    假设你想找到一个 id = 3 的对象。

    1.查找: 它在数组中搜索一个元素,如果找到,则返回该元素,否则返回未定义。它返回提供的数组中满足提供的测试功能的第一个元素的值。 reference

    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。过滤器: 它在数组中搜索元素并过滤掉所有匹配条件的元素。它返回一个包含所有元素的新数组,如果没有一个符合条件,则返回一个空数组。 reference

    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() 方法测试数组中是否存在至少一个元素,该元素通过了提供的函数实现的测试。它返回一个布尔值。 reference

    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' });
    }
    

    【讨论】:

      【解决方案7】:

      假设我们有一个对象数组,你想检查 name 的值是否是这样定义的,

      let persons = [ {"name" : "test1"},{"name": "test2"}];
      
      if(persons.some(person => person.name == 'test1')) {
          ... here your code in case person.name is defined and available
      }
      

      【讨论】:

      • 请添加几句话来解释您的代码在做什么,以便您的回答获得更多的支持。
      • 如果我想比较具有 {"name" : "test1", "age": 30} 等 2 个属性的对象怎么办?
      【解决方案8】:

      试试这个

      第一种方法使用一些

        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)
      

      第二种方法使用包含,映射

         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} 等 2 个属性的对象怎么办?
      • @probitaille 你可以使用 && 运算符 const obj = {"name" : "test1", "age": 30}; arr.some(a => a.name === obj.name && a.age === obj.age);
      【解决方案9】:

      我喜欢 Andy 的回答,但 id 不一定是唯一的,所以这也是我想出的创建唯一 ID 的方法。也可以在jsfiddle 进行检查。请注意,如果之前删除了任何内容,arr.length + 1 很可能无法保证唯一的 ID。

      var array = [ { id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 3, username: 'ted' } ];
      var usedname = 'bill';
      var newname = 'sam';
      
      // don't add used name
      console.log('before usedname: ' + JSON.stringify(array));
      tryAdd(usedname, array);
      console.log('before newname: ' + JSON.stringify(array));
      tryAdd(newname, array);
      console.log('after newname: ' + JSON.stringify(array));
      
      function tryAdd(name, array) {
          var found = false;
          var i = 0;
          var maxId = 1;
          for (i in array) {
              // Check max id
              if (maxId <= array[i].id)
                  maxId = array[i].id + 1;
      
              // Don't need to add if we find it
              if (array[i].username === name)
                  found = true;
          }
      
          if (!found)
              array[++i] = { id: maxId, username: name };
      }
      

      【讨论】:

      • 我喜欢其他答案的简单性,我刚刚发布了我的答案以添加对唯一 ID 的检查
      • 感谢您的回答 Uxonith。目前我不需要唯一 ID,因为我不会从数组中删除用户。我会把这个决议放在我的口袋里,以备不时之需。再次感谢
      【解决方案10】:

      您可以对数组进行原型设计以使其更加模块化,试试这样的方法

          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)
      

      【讨论】:

        【解决方案11】:

        接受的答案也可以使用 .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 }); }
         }
        

        【讨论】:

          【解决方案12】:

          这是一个使用.map().includes()的ES6方法链:

          const arr = [ { id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 2, username: 'ted' } ]
          
          const checkForUser = (newUsername) => {
                arr.map(user => {
                  return user.username
                }).includes(newUsername)
              }
          
          if (!checkForUser('fred')){
            // add fred
          }
          
          1. 映射现有用户以创建用户名字符串数组。
          2. 检查该用户名数组是否包含新用户名
          3. 如果不存在,请添加新用户

          【讨论】:

            【解决方案13】:

            出于某种原因,我确实尝试了上述步骤,但它似乎对我不起作用,但这是我对自己问题的最终解决方案,可能对任何阅读本文的人都有帮助:

            let pst = post.likes.some( (like) => {  //console.log(like.user, req.user.id);
                                                 if(like.user.toString() === req.user.id.toString()){
                                                     return true
                                                 } } )
            

            这里的 post.likes 是一个喜欢帖子的用户数组。

            【讨论】:

              【解决方案14】:

              这可以通过几个数组方法和几种不同的方式相当简单地完成。

              1。只需将新对象推送到源数组并忽略函数返回的值(true,或使用 .push() 时的数组长度)

              下面,我首先将数组映射到仅包含用户名的新浅数组,然后检查该数组.includes() 是否为指定的用户名。如果是这样,我会根据|| 运算符的性质返回true。否则,我将指定用户名的新对象推送回源对象数组。

              const arr = [{ id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 3, username: 'ted' }];
              const usernameCheck = (arr, usr) => arr.map(u => u.username).includes(usr) || arr.push({ id: arr.length+1, username: usr });
              usernameCheck(arr, 'jeremy');
              console.log(arr);

              2。返回数组而不是简单地返回true,或者使用.push()时的数组长度:

              如果您希望获得更大的灵活性,还可以通过多种方式对此进行改进。如果您不想返回 true 而是希望返回新数组以供立即使用,我们可以通过简单地在函数末尾返回数组来使用 , 运算符,无论是否推送制成。用这个方案,还是把原来的数组push到了,因为我们返回了数组,所以我们可以直接在函数执行上执行我们的console.log(),而不需要先运行函数,然后再记录数组的内容。

              const arr = [{ id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 3, username: 'ted' }];
              const usernameCheck = (arr, usr) => (arr.map(u => u.username).includes(usr) || arr.push({ id: arr.length+1, username: usr }), arr);
              console.log(usernameCheck(arr, 'jeremy'));

              3。使用浅拷贝,不改变源数组:

              另一方面,如果您只想返回新数组的浅表副本而不直接推送到源数组,则可以使用扩展运算符 ....concat() 方法(如果您愿意) :

              const arr = [{ id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 3, username: 'ted' }];
              const usernameCheck = (arr, usr) => arr.map(u => u.username).includes(usr) ? [...arr] : [...arr, { id: arr.length+1, username: usr }];
              console.log('This will return the array with the added username:\n\nusernameCheck(arr, \'jeremy\')', usernameCheck(arr, 'jeremy'));
              console.log('But the original array remains untouched:\n\narr', arr);

              【讨论】:

                【解决方案15】:

                数组的原生函数有时比普通循环慢 3X - 5X 倍。加上原生功能无法在所有浏览器中运行,因此存在兼容性问题。

                我的代码:

                <script>
                  var obj = [];
                
                  function checkName(name) {
                    // declarations
                    var flag = 0;
                    var len = obj.length;   
                    var i = 0;
                    var id = 1;
                
                    // looping array
                    for (i; i < len; i++) {
                        // if name matches
                        if (name == obj[i]['username']) {
                            flag = 1;
                            break;
                        } else {
                            // increment the id by 1
                            id = id + 1;
                        }
                    }
                
                    // if flag = 1 then name exits else push in array
                    if (flag == 0) {
                      // new entry push in array        
                      obj.push({'id':id, 'username': name});
                    }
                  }
                  // function end
                
                  checkName('abc');
                </script>
                

                这样你可以更快地获得结果。

                注意:我没有检查传递的参数是否为空,如果你愿意你可以检查它或者写一个正则表达式进行特定的验证。

                【讨论】:

                  【解决方案16】:

                  Lodash 中的xorWith 可以用来实现这个

                  let objects = [ { id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 2, username: 'ted' } ]
                  let existingObject = { id: 1, username: 'fred' };
                  let newObject = { id: 1729, username: 'Ramanujan' }
                  
                  _.xorWith(objects, [existingObject], _.isEqual)
                  // returns [ { id: 2, username: 'bill' }, { id: 2, username: 'ted' } ]
                  
                  _.xorWith(objects, [newObject], _.isEqual)
                  // returns [ { id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 2, username: 'ted' } ,{ id: 1729, username: 'Ramanujan' } ]
                  

                  【讨论】:

                    【解决方案17】:

                    在这里查看:

                    https://stackoverflow.com/a/53644664/1084987

                    你可以在之后创建类似 if 条件的东西,比如

                    if(!contains(array, obj)) add();
                    

                    【讨论】:

                      【解决方案18】:

                      你也可以试试这个

                       const addUser = (name) => {
                          if (arr.filter(a => a.name == name).length <= 0)
                              arr.push({
                                  id: arr.length + 1,
                                  name: name
                              })
                      }
                      addUser('Fred')
                      

                      【讨论】:

                        【解决方案19】:
                        function number_present_or_not() {
                          var arr = [2, 5, 9, 67, 78, 8, 454, 4, 6, 79, 64, 688];
                          var found = 6;
                          var found_two;
                          for (i = 0; i < arr.length; i++) {
                            if (found == arr[i]) {
                              found_two = arr[i];
                              break;
                            }
                          }
                          if (found_two == found) {
                            console.log('number present in the array');
                          } else {
                            console.log('number not present in the array');
                          }
                        }
                        

                        【讨论】:

                          【解决方案20】:
                          const __checkIfElementExists__ = __itemFromArray__ => __itemFromArray__.*sameKey* === __outsideObject__.*samekey*;
                          
                              if (cartArray.some(checkIfElementExists)) {
                                  console.log('already exists');
                              } else {
                                  alert('does not exists here')
                          
                          

                          【讨论】:

                          • 这确实将指定的用户名添加到源数组中,正如问题所问的那样。
                          猜你喜欢
                          • 1970-01-01
                          • 1970-01-01
                          • 2022-01-17
                          • 1970-01-01
                          • 2019-09-15
                          • 2020-11-30
                          • 2014-09-01
                          • 1970-01-01
                          • 1970-01-01
                          相关资源
                          最近更新 更多