277

If I have the following array of objects:

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

Is there a way to loop through the array to check whether a particular username value already exists and if it does do nothing, but if it doesn't to add a new object to the array with said username (and new ID)?

Thanks!

Andy
  • 61,948
  • 13
  • 68
  • 95
user2576960
  • 2,883
  • 2
  • 14
  • 10
  • 1
    Are Bill and Ted supposed to have the same ID? – user2357112 Apr 03 '14 at 17:18
  • Why there's two elements with the same `id`? Is that possible that elements will be removed from this array, or can we be sure that the new element will always have `id` equal to `arr.length + 1`? – raina77ow Apr 03 '14 at 17:18
  • If you don't want to loop through it, check this Q&A for extending array prototype, http://stackoverflow.com/questions/1988349/array-push-if-does-not-exist. – Cem Özer Apr 03 '14 at 17:19
  • native functions are slower compared to normal loops and their support is limited to some browser versions. check my answer below. – Zaheen Nov 10 '17 at 09:21
  • this is a fundamentally wrong question because you can do that by avoiding the use of Arrays. – Bekim Bacaj Nov 10 '17 at 09:28
  • @user2576960 Please check my solution when you have a moment, as it achieves exactly this succinctly in a simple, one line function. I provided a few different ways of achieving this, but I feel as those my **#1** or **#2** solutions best fit what you are looking for. – Brandon McConnell May 14 '21 at 14:21

22 Answers22

413

I've assumed that ids are meant to be unique here. some is a great function for checking the existence of things in arrays:

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'));
Andy
  • 61,948
  • 13
  • 68
  • 95
  • 2
    Thanks Andy this is a very clean solution to the problem and is working very well. I had not come across the some method before. Your assumption was correct my ID example was just a typo, I was using arr.length + 1 to determine the ID. – user2576960 Apr 04 '14 at 08:19
  • 3
    Beware that IE8 and earlier do not support the some function. – BetaRide Oct 13 '14 at 06:50
  • Can the found function be made into an IF? Something like: if (arr.some(function (el) { el.Id == someId) and it will return either true or false if it exists or not? – stibay Sep 24 '15 at 17:18
  • @stibay, `some` _does_ return a boolean. `found` will either be `true` or `false` depending on whether the condition in the callback is met. – Andy Sep 24 '15 at 17:21
  • yea I got that, but I want to drop the found variable and just have the "found function" in an IF statement. – stibay Sep 24 '15 at 17:22
  • 3
    Oh, sure: `if (arr.some(function (el) { return el.Id == someId; })) { // do something }`. Don't forget that `return` or you won't get anything back. – Andy Sep 24 '15 at 17:26
  • 1
    Hi, If I found the value how can I access the id? – Kusal Kithmal Dec 31 '19 at 12:15
  • 1
    Very nice solution and just what I was looking for. Thanks for that! – z0mbieKale Jun 09 '20 at 09:33
  • Isn't a find with a condition better in terms of efficiency ? Because stopping iteration when first element is found. On a big list, it should do a difference. or a for loop with a break – Uneconscience UneSource Dec 01 '22 at 15:02
  • Not necessarily @UneconscienceUneSource. Both `some` and `find` short-circuit in the same way. In my defence `find` only appeared in browser APIs late the previous year so was relatively unknown whereas `some` had been around for three years prior to this answer being written. – Andy Dec 01 '22 at 15:40
  • Some is still more appropriate than find here since we only care about existence. Find is better when we actually need the object that matched the condition, which isn't the case here. – Unmitigated Feb 20 '23 at 16:08
72

This small snippets works for me..

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

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

console.log(arrayOfObject.some(checkUsername))

if you have array of elements like ['john','marsh'] then we can do some thing like this

const checkUsername = element => element == 'john';
    
console.log(arrayOfObject.some(checkUsername))
Guruprasad
  • 753
  • 6
  • 23
Sagar
  • 4,473
  • 3
  • 32
  • 37
  • 3
    Rather elegant approach! - More details and examples using `.some` found here - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some – James Marino Jul 09 '18 at 23:43
49

It's rather trivial to check for existing username:

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

But it's not so obvious what to do when you have to add a new user to this array. The easiest way out - just pushing a new element with id equal to 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

It will guarantee the IDs uniqueness, but will make this array look a bit strange if some elements will be taken off its end.

raina77ow
  • 103,633
  • 15
  • 192
  • 229
  • Thanks for this. I went with Andy's solution in the end because it's a more succinct way of achieving the same thing. I won't be removing users at any point so IDs should remain consistent. The check allows users to log in, out and back in again without the array growing overtime. Just for info I'm using this function in conjunction with passport.js and I haven't been able to find a way of removing users from the array without playing with passport code itself. This solution works nicely. – user2576960 Apr 04 '14 at 08:28
27

There could be MULTIPLE POSSIBLE WAYS to check if an element(in your case its Object) is present in an array or not.

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

let say you want to find an object with id = 3.

1. find: It searches for an element in an array and if it finds out then it returns that element else return undefined. It returns the value of the first element in the provided array that satisfies the provided testing function. 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. filter: It searches for elements in an array and filters out all element that matches the condition. It returns a new array with all elements and if none matches the condition then an empty array. 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: The some() method tests whether at least one element is present in an array that passes the test implemented by the provided function. It returns a Boolean value. 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' });
}
DecPK
  • 24,537
  • 6
  • 26
  • 42
  • 1
    Coming from python, I was surprised to see that nobody is worrying about efficiency. The first solution, with find, seems better because iterations will stop when a first matching element is found. or a for loop with a break – Uneconscience UneSource Dec 01 '22 at 14:59
21

This is what I did in addition to @sagar-gavhane's answer

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)
Kamran
  • 371
  • 1
  • 4
  • 15
Michael Enitan
  • 512
  • 6
  • 10
17

I think that, this is the shortest way of addressing this problem. Here I have used ES6 arrow function with .filter to check the existence of newly adding username.

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

Kushan Randima
  • 2,174
  • 5
  • 31
  • 58
9

Let's assume we have an array of objects and you want to check if value of name is defined like this,

let persons = [ {"name" : "test1"},{"name": "test2"}];

if(persons.some(person => person.name == 'test1')) {
    ... here your code in case person.name is defined and available
}
Hasan Zahran
  • 1,364
  • 16
  • 14
3

try this

first method using some

  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)

second method using 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)
Trilok Singh
  • 1,227
  • 12
  • 10
  • What if I want to compare objects with 2 attributes like {"name" : "test1", "age": 30} ? – probitaille Jul 17 '20 at 13:27
  • @probitaille you can use && operator const obj = {"name" : "test1", "age": 30}; arr.some(a => a.name === obj.name && a.age === obj.age); – Kamran Nov 25 '20 at 15:34
2

You could prototype your array to make it more modular, try something like this

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

And you can use it as:

 yourArray.hasElement(yourArrayElement)
Jonathan Marzullo
  • 6,879
  • 2
  • 40
  • 46
Luis Saraza
  • 346
  • 3
  • 12
2

Accepted answer can also be written in following way using arrow function on .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 }); }
 }
Hemadri Dasari
  • 32,666
  • 37
  • 119
  • 162
2

Here is an ES6 method chain using .map() and .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. Map over existing users to create array of username strings.
  2. Check if that array of usernames includes the new username
  3. If it's not present, add the new user
Len Joseph
  • 1,406
  • 10
  • 21
1

I like Andy's answer, but the id isn't going to necessarily be unique, so here's what I came up with to create a unique ID also. Can be checked at jsfiddle too. Please note that arr.length + 1 may very well not guarantee a unique ID if anything had been removed previously.

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 };
}
Uxonith
  • 1,602
  • 1
  • 13
  • 16
  • I like the simplicity in the other answers, I just posted mine to add the check for unique ID – Uxonith Apr 03 '14 at 17:28
  • Thanks for your answer Uxonith. At the moment I do not have a need for unique ID because I won't be removing users from the array. I will keep this resolution in my back pocket in case the need arises. Thanks again – user2576960 Apr 04 '14 at 08:40
1

i did try the above steps for some reason it seams not to be working for me but this was my final solution to my own problem just maybe helpful to any one reading this :

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

here post.likes is an array of users who liked a post.

1

Greatly simplifying my previous solutions here and providing better performance by not iterating over the entire array unnecessarily before checking for the existence of the specified ID.

This should be the simplest solution (I think):

const users = [{ id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 3, username: 'ted' }];
const addUser = (username) => {
  const user = users.find((user) => user.username === username);
  if (user) return { ...user, new: false };
  const newUser = {
    id: users.length + 1,
    username,
  };
  users.push(newUser);
  return { ...newUser, new: true };
};

Here is how that might look as a live example:

const users = [{ id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 3, username: 'ted' }];
const addUser = (username) => {
  const user = users.find((user) => user.username === username);
  if (user) return { ...user, new: false };
  const newUser = {
    id: users.length + 1,
    username,
  };
  users.push(newUser);
  return { ...newUser, new: true };
};

// a little extra scripting here to support the input and button in the example

const form = document.querySelector('form');
const input = document.querySelector('input');
const span = document.querySelector('span');
const pre = document.querySelector('pre');

const syncDataWithPre = () => {
  pre.innerHTML = JSON.stringify(users, null, 2);
};

form.onsubmit = (e) => {
  e.preventDefault();
  span.textContent = '';
  if (input.value) {
    const user = addUser(input.value);
    const { new: isNew, ...userDetails } = user;
    span.classList[isNew ? 'add' : 'remove']('new');
    span.textContent = `User ${isNew ? 'added' : 'already exists'}`;
  }
  input.value = '';
  syncDataWithPre();
};

syncDataWithPre();
body {
  font-family: arial, sans-serif;
}
span {
  display: block;
  padding-top: 8px;
  font-weight: 700;
  color: #777;
}
span:empty {
  display: none;
}
.new {
  color: #0a0;
}
.existing: {
  color: #777;
}
<form>
  <input placeholder="New username" />
  <button>Add user</button>
</form>
<span></span>
<pre></pre>
Brandon McConnell
  • 5,776
  • 1
  • 20
  • 36
0

Native functions of array are sometimes 3X - 5X times slower than normal loops. Plus native functions wont work in all the browsers so there is a compatibility issues.

My Code:

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

This way you can achieve result faster.

Note: I have not checked if parameter passed is empty or not, if you want you can put a check on it or write a regular expression for particular validation.

Zaheen
  • 821
  • 9
  • 11
0

xorWith in Lodash can be used to achieve this

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' } ]
sudo bangbang
  • 27,127
  • 11
  • 75
  • 77
0

Check it here :

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

You can create something like if condition afterwards, like

if(!contains(array, obj)) add();
Clyde
  • 732
  • 8
  • 19
0
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');
  }
}
Mario Petrovic
  • 7,500
  • 14
  • 42
  • 62
Nakkeeran
  • 69
  • 4
0

You can try this also

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

Please have a look on given example

$(document).ready(function(){
  const arr = document.querySelector(".list");
    var abcde = [{ id: 1, username: 'fred' }, { id: 2, username: 'bill' }, { id: 2, username: 'ted' }];
  $("#btnCheckUser").click(function() {
    var tbUsername = $("#tbUsername").val();
    if (abcde.some(obj => obj.username === tbUsername)) {
        alert('existing user ' + tbUsername);
        return;
    }
    else {
        abcde.push({ id: abcde.length + 1, username: tbUsername });
        alert('added new user ' + tbUsername);
        arr.appendChild(createArray(tbUsername));
        return;
    }
  });
  
  function createArray(name) {
    let li = document.createElement("li");
    li.textContent = name;
    return li;
  }
  abcde.forEach((x) => arr.appendChild(createArray(x.username)));

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>

<p>Add text and click on Check.</p>

<input type="text" id="tbUsername" />
<button type="button" id="btnCheckUser">Check</button>

<div class="list">
  <ul></ul>
</div>
Malik Zahid
  • 593
  • 5
  • 13
0

I was given a condition to check the data in the table of the mysql database the object array of my table consist of the id, latitude and longitude as column names, I have to check whether the location is in the database else insert this into the table so: I created a function of handle submit called by a button,

handle Submit = (event) => {
        const latitude = document.getElementById("latitude").innerHTML;
        const longitude = document.getElementById("longitude").innerHTML;
        const found = this.state.data.some((el) => el.latitude === latitude);
    if (!found) {
      Axios.post("http://localhost:3001/api/insert", {
        latitude: latitude,
        longitude: longitude,
      }).then(() => {
        alert("successful insert");
      });
      console.log(latitude, longitude);
    }
  };

Here you can see the conditional statement for inserting if not exist in the database.

-1
const __checkIfElementExists__ = __itemFromArray__ => __itemFromArray__.*sameKey* === __outsideObject__.*samekey*;

    if (cartArray.some(checkIfElementExists)) {
        console.log('already exists');
    } else {
        alert('does not exists here')

emkarachchi
  • 750
  • 1
  • 7
  • 18