检查对象值是否存在于对象的Javascript数组中,如果不存在,则将新对象添加到数组中


146

如果我有以下对象数组:

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

有没有一种方法可以遍历数组,以检查特定的用户名值是否已经存在,并且不执行任何操作,但是是否不使用该用户名(和新ID)向该数组添加新对象?

谢谢!


1
Bill和Ted是否应该具有相同的ID?
user2357112支持Monica 2014年

为什么有两个元素相同id?是否有可能从该数组中删除元素,或者我们可以确保新元素始终id等于arr.length + 1
raina77ow

如果您不想遍历整个循环,请查看此问答,以扩展数组原型stackoverflow.com/questions/1988349/…
CemÖzer2014年

与正常循环相比,本机函数要慢一些,并且它们的支持仅限于某些浏览器版本。在下面检查我的答案。
Zaheen

这是一个根本上错误的问题,因为您可以通过避免使用数组来做到这一点。
Bekim Bacaj

Answers:


234

我假设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'));


1
谢谢Andy,这是解决问题的非常干净的方法,并且运行良好。我以前没有遇到过某种方法。您的假设是正确的,我的ID示例只是一个错字,我使用arr.length +1确定ID。
user2576960

3
注意IE8和更早版本不支持某些功能。
BetaRide

可以将找到的函数设为IF吗?像这样的东西:if(arr.some(function(el){el.Id == someId),如果存在或不存在,它将返回true或false?
stibay

@stibay,some 确实返回布尔值。found将是truefalse取决于是否满足回调中的条件。
安迪

1
哦,确定:if (arr.some(function (el) { return el.Id == someId; })) { // do something }。不要忘记这一点,return否则您将一无所获。
安迪

26

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

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结合使用,而且我无法找到一种无需使用护照代码本身就能从阵列中删除用户的方法。该解决方案效果很好。
user2576960


10

我认为,这是解决此问题的最短方法。在这里,我将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);

链接到小提琴


3

除了@ sagar-gavhane的答案,这是我所做的

const newUser = {_id: 4, name: 'Adam'}
const users = [{_id: 1, name: 'Fred'}, {_id: 2, name: 'Ted'}, {_id: 3, '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; } ...
Michael Enitan '19

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

1

我喜欢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 2014年

感谢您的答复Uxonith。目前,我不需要唯一的ID,因为我不会从阵列中删除用户。万一有需要,我会把这个分辨率放在我的后兜里。再次感谢
user2576960 2014年

1

您可以原型化数组以使其更具模块化,请尝试类似的操作

    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)

1

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

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是喜欢该帖子的一系列用户。


1

试试这个

第一种方法使用一些

  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)

如果我想比较具有2个属性(如{“ name”:“ test1”,“ age”:30})的对象怎么办?
probitaille

1

假设我们有一个对象数组,您想检查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
}

请添加一些句子来解释您的代码在做什么,以便您获得更多的支持。
模糊分析

如果我想比较具有2个属性(如{“ name”:“ test1”,“ age”:30})的对象怎么办?
probitaille

1

这是使用.map()和的ES6方法链.includes()

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. 如果不存在,请添加新用户

0

数组的本机函数有时比正常循环慢3到5倍。加上本机功能无法在所有浏览器中使用,因此存在兼容性问题。

我的代码:

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

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

注意:我尚未检查传递的参数是否为空,如果需要,可以对其进行检查或编写用于特定验证的正则表达式。


0

xorWith 在Lodash中可以用来实现这一目标

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' } ]


0

函数number_present_or_not(){ var arr = [ 2,5,9,67,78,8,454,4,6,79,64,688 ] ; 找到var = 6; var found_two; 对于(i = 0; i

    }
    if ( found_two == found )
    {
        console.log("number present in the array");
    }
    else
    {
        console.log("number not present in the array");
    }
}

-1

最佳实践就是这样。

var arr = ["a","b","c","d"];
console.log(arr.includes("a")); //---- true;
console.log(arr.includes("k")); //---- false;
console.log(arr.includes("c")); //---- true;

18
问题是关于对象数组的问题,这是行不通的。
Adrian Enriquez

这不是问题的正确答案。
阿桑·穆赫塔

这个答案不能满足问题中提到的要求。
Savan Gadhiya
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.