Find duplicate property values in an Array of Objects in JavaScript

Finding duplicate property values in an Array of Objects in JavaScript is not always that simple if you thought, so let’s dive in! A few days ago I needed to work this out, so I thought let’s write it down, so I could use it later again!

Array of Objects

Let’s define an example Array of Objects, where each Object is a user:

var myArray = [
  {id: 1, name: 'Foo Bar', email: 'foo@bar.com'},
  {id: 2, name: 'Bar Foo', email: 'bar@foo.com'},
  {id: 3, name: 'Joe Ocean', email: 'joe@ocean.com'},
  {id: 3, name: 'Jenny Block', email: 'foo@bar.com'},
];

You can see that there are a few property value’s that are duplicated. The id and the email property. But if you can imagine in a real application you don’t know if someone else has used an email address before. So you need to check it before you can save it.

I’m not gonna discuss a process how you should do this in an application. But just showing how you could see if an Array of Objects has duplicated property values.

JavaScript function to check duplicate property values

function checkDuplicateInObject(propertyName, inputArray) {
  var seenDuplicate = false,
      testObject = {};

  inputArray.map(function(item) {
    var itemPropertyName = item[propertyName];    
    if (itemPropertyName in testObject) {
      testObject[itemPropertyName].duplicate = true;
      item.duplicate = true;
      seenDuplicate = true;
    }
    else {
      testObject[itemPropertyName] = item;
      delete item.duplicate;
    }
  });

  return seenDuplicate;
}

Let’s create a function with 2 parameters. I will explain everything from the function, so everyone could follow this :-).

The propertyName you want to check in each Object and the inputArray, where you are gonna check the Objects from.

We define 2 variables at the start. seenDuplicate, the value is gonna be false as default. After that, we create a testObject to put in every Object we are looping trough.

We use the .map() function to loop trough the Array (read the article .map() vs .forEach() vs .for() to know why I picked .map()). For every Object we check if there is an property in the testObject with the name of the id, email or something else. Because the in keyword checks the property name not the value of a property!

If there isn’t a property name in the testObject that is the same as the item’s property value, then it will be placed in the Object. If it is already in the testObject it will be marked as duplicated. But more important, seenDuplicate will be true!

After the .map() function we return the seenDuplicate variable. So the result of the function, if we check the id property will be true. If we check it with the property name it will be false. Or with email, it will return true!

Demo

In the demo below you can test the output of the console.

JS Bin on jsbin.com

If you have some question’s or comments on this post, please add them to the comments 🙂

ES6 VAR, LET and CONST explained!

ES6 (ES2015) is one of the buzzwords in JavaScript nowadays. There are a lot of new features in it. Let’s watch the var, let and const!

What is a VAR?

VAR can be used for anything everywhere

The var keyword can be used everywhere. You can put in all kinds of information. Strings, Int, Object, Array, Function. That is great, well most of the time!

Variables can be used for everything, but also everywhere. You can access a var from inside a function, object, if-else statement, really everywhere! That maybe sounds cool, but can have a big effect on the performance of a website or web-application.

Globally scoped

A var is or can be globally scoped. Cool to access everything from inside anything! But is that good? With the coming of ES6 there are a few alternatives ahead. There are called let and const. They have different behavior than var. But let’s talk about that later.

Can be changed later

A variable can be defined with a string, later on, reassigned to an integer and later it could be a function. That is a power but also a weakness.

var globalVariable;

globalVariable = 'I Love Pizza!';

console.log(globalVariable); // Will be 'I Love Pizza!'

Now I defined a global variable (yes I do love pizza :-)), right after it I added a string to it. So you can see, you can define it and later on change it to the other value.

function iChangeTheVariable() {
    globalVariable = [59, 600, 843];
}

iChangeTheVariable();

console.log(globalVariable); // Will be [59, 600, 843]

So guess what, the globalVariable is change. Sounds cool right! Well If it was your intention to change it, yes! But if you didn’t know that you already used that variable, then it is a problem! There is the weakness!!

Can be locally scoped

Now you can see the danger of globally scoped variables. So if I may advise you, never use globally scoped variables.

(function() {
    var var1 = 'variable 1 value in parent scope';

    (function() {
        // Scope 1
        var1 = 'variable 1 value in scope 1';
        console.log('scope 1: ', var1); // Is 'variable 1 value in scope 1'
    }());

    (function() {
        // Scope 2
        var1 = 'variable 1 value in scope 2';
        console.log('scope 2: ', var1); // Is 'variable 1 value in scope 2'
    }());

    console.log('Parent scope: ', var1); // Is 'variable 1 value in parent scope'

}());
console.log('Global scope: ', var1); // Is undefined

You can make the variable locally scoped, by putting it inside a function. Like the example here, if you execute the function in your console, the last console.log() with “Parent scope:” in it, will be changed by the one before it!

Can be hoisted

Variables can be hoisted. Hoisted means, declare them all on top of the function (I hope you don’t put everything in the global scope!).

(function() {

    var localVar1, localVar2, localVar3;

    localVar1 = 'Variable value 1';
    localVar2 = [74, 88, 97, 112];
    localVar3 = {name: 'Ray', website: 'http://personaldomain.com'};

}());

This how most developer usally hoist their variables. This is to make sure that they declared the variables before the got a value. But also to prevent the variables be globally accessible.

What is a LET?

Let is block scoped

let is one of the new kids on the block in ES6. A let variable is block scoped. You can create a scope by any {}. With a function, for and while loop and a lot more.

Finally, a variable type that is not globally but locally scoped!

can be changed later

A let variable can be changed later, but only if it is in the same scope as where it is declared! It is declared in the other scope, it is just a new variable that is defined.

This example will run in the latest version of Google Chrome (not in Safari)

(function() {
    let letVar1 = 'Let variable 1 value in parent scope';

    (function() {
        // Scope 1
        let letVar1 = 'Let variable 1 value in scope 1';
        console.log('scope 1: ', letVar1); // Is 'Let variable 1 value in scope 1'
    }());

    (function() {
        // Scope 2
        let letVar1 = 'Let variable 1 value in scope 2';
        console.log('scope 2: ', letVar1); // Is 'Let variable 1 value in scope 2'
    }());

    console.log('Parent scope: ', letVar1); // Is 'Let variable 1 value in parent scope'

}());
console.log('Global scope: ', letVar1); // Is undefined

If you tried to paste this snippet into the devtools console you will see that the parent scope, scope 1 & 2 give different values. That is because it is block scoped. The global scope will give an error that it is undefined.

With the normal var you can just give letVar1 a new value. But since a let can’t be re-defined later, this is not possible for the let.

If we would forget to assign letVar1 in scope 1, then the console in scope 1 would output “Let variable 1 value in parent scope”. Because it will lookup to the parent scope.

Can’t be hoisted

If you try to hoist let variables, then you will get errors. So define a let and give it a value. If you first try to define it and give it a value later, you will end with errors!

What is a CONST?

The things that you read about const is that the are immutable. Most people think that it means that you can’t change the value, but instead you can change the value. But you can’t re-assign the reference to the const itself.

Const is block scoped

A const is block scoped, the same as the let variable. In the other scope, you can define the const again. But you can’t re-assign the same const in the other scope.

(function() {
    const constVar1 = 'const variable 1 value in parent scope';

    (function() {
        // Scope 1
        const constVar1 = 'const variable 1 value in scope 1';
        console.log('scope 1: ', constVar1);
        // scope 1:  const variable 1 value in scope 1
    }());

    console.log('Parent scope: ', constVar1);
    // Parent scope:  const variable 1 value in parent scope

}());

In this example, you can see that it is possible to assign a constant with the same name in a different scope with the other value.

Can’t be re-assigned

(function() {
    const constVar1 = 'const variable 1 value in parent scope';

    (function() {
        // Scope 1
        console.log('scope 1: ', constVar1);
        // scope 1:  const variable 1 value in parent scope
        constVar1 = 'const variable 1 value in scope 1';
        // Is Identifier 'constVar1' has already been declared
        console.log('scope 1: ', constVar1);    }());

}());

In this example, you can see that it is not possible to re-assign the same constant with a different value.

Can’t be hoisted

Because you can’t re-assign a const, you know it is not possible to hoist them. For hoisting, you need to re-assign.

ES6 / ES2015

If you want to check which browser (or the browser you are currently using) supports ES6 /ES2015, check:http://kangax.github.io/compat-table/es6/

If something is not clear or confusing about var, let or const please add your questions to the comments!

JavaScript Basics: Add something to the beginning of an array in JavaScript

How to add something (Object, Array, String, Number) to an Array in JavaScript. Well that is simply done with the Array.push() method.

var arrayName = ['1', '2', '3'];
arrayName.push({
     property1: 'First property of Object',
     property2: ['Array', 'of', 'Items']
});
arrayName.push('Last item');

The result will be:

[
  '1',
  '2',
  '3',
  {
    property1: 'First property of Object',
    property2: ['Array', 'of', 'Items']
  },
  'Last item'
]

That was simple! Right? Every time you push something to the Array, it will be added to the end. But what if you need to add something to the beginning of the array?

That is also simple, use the Array.unshift() method.

var arrayName = ['1', '2', '3'];
arrayName.unshift({
  property1: 'First property of Object',
  property2: ['Array', 'of', 'Items']
},'Second item');

The result of the code above will be:

[
  {
    property1: 'First property of Object',
    property2: ['Array', 'of', 'Items']
  },
  'Second item',
  '1',
  '2',
  '3'
]

I thought it would be useful in some cases to put something at the beginning of an exciting Array. So I hope this will help you to use it. 🙂

Check the resources of W3Schools if you want to read more about the Array.unshift() or Array.push() method.

The JavaScript array.forEach() method doesn’t return anything!

A while ago working on a cool Angular2 project I discovered some weird behavior, weird because I didn’t realise it was working that way.

I was checking if an id property of an object, was already in an array. If it was, it won’t push it again. It is wasn’t in there, it could push the object in the array.

It doesn’t seem that difficult. So I created a little function so I could check it from anywhere in my application. (take into account that the code is from an Angular2 Typescript application.)

private doesFormExistsInSubmittedArray(list, val) {
    if (list !== undefined && list.length > 0) {
        list.forEach(function (item, index, arr) {
            if(item.formObject.id === val.id) {
                return true;
            }
        });
    }
    return false;
}

But every time the function was fired, in the end where duplicated object’s in the array! At that moment, I thought WHAT? This was a simple thing that I overlooked. I spend hours to find the issue. Even a smarter team member didn’t find the solution.

But in many cases in programming, you wonder why something doesn’t work, but it should. Well, this was 1 of these cases.

We where comparing the array.forEach() with the for() loop. The simplest thing to see (if you already used the forEach() function) is that the forEach() is a bit easier to read. With the for() loop, you need a bit more code.

One of the major things we didn’t realize, the array.forEach() function is creating a different scope, because it is a function. So when it meets the if statement, and will come’s across the return true, it doesn’t move the return outside of the forEach() function.

A second remark of the forEach() function is: The for() loop will stop with running after you return a something. But the forEach() function will first finish running trough the array when it is finished it can return something.

That was my AHA moment! That I didn’t saw that! Well, that the next question was, how do we get that returned value outside of its scope.

Pretty simple, declare a variable (in Typescript you can use let) with a false value. When running trough the forEach() function and it meets the if statement, it will assign true to the variable. When the forEach() is done running, it will return the variable. So when you run this function, it will run true or false.

Eventually, this is the result that works (Typescript).

private doesFormExistsInSubmittedArray(list, val) {
    let found = false;
    if (list !== undefined && list.length > 0) {
        list.forEach(function (item, index, arr) {
            if(item.formObject.id === val.id) {
                found = true;
            }
        });
    }
    return found;
}

This is the Vanilla JavaScript version.

function doesFormExistsInSubmittedArray(list, val) {
    var found = false;
    if (list !== undefined && list.length > 0) {
        list.forEach(function (item, index, arr) {
            if(item.formObject.id === val.id) {
                found = true;
            }
        });
    }
    return found;
}

Hopefully, this will help you to get the returned value from the forEach() function! If you have problems or questions with this? Or have a different problem with the for() loop or forEach()method? Please let me know in the comments!