Categories
arrays javascript lodash underscore.js

Update if exists or add new element to array of objects – elegant way in javascript + lodash

So I have an array of objects like that:

var arr = [
{uid: 1, name: "bla", description: "cucu"},
{uid: 2, name: "smth else", description: "cucarecu"},
]

uid is unique id of the object in this array. I’m searching for the elegant way to modify the object if we have the object with the given uid, or add a new element, if the presented uid doesn’t exist in the array. I imagine the function to be behave like that in js console:

> addOrReplace(arr, {uid: 1, name: 'changed name', description: "changed description"})
> arr
[
{uid: 1, name: "bla", description: "cucu"},
{uid: 2, name: "smth else", description: "cucarecu"},
]
> addOrReplace(arr, {uid: 3, name: 'new element name name', description: "cocoroco"})
> arr
[
{uid: 1, name: "bla", description: "cucu"},
{uid: 2, name: "smth else", description: "cucarecu"},
{uid: 3, name: 'new element name name', description: "cocoroco"}
]

My current way doesn’t seem to be very elegant and functional:

function addOrReplace (arr, object) {
var index = _.findIndex(arr, {'uid' : object.uid});
if (-1 === index) {
arr.push(object);
} else {
arr[index] = object;
}
}

I’m using lodash, so I was thinking of something like modified _.union with custom equality check.

You can use an object instead of an array:

var hash = {
'1': {uid: 1, name: "bla", description: "cucu"},
'2': {uid: 2, name: "smth else", description: "cucarecu"}
};

The keys are the uids. Now your function addOrReplace is simple like this:

function addOrReplace(hash, object) {
hash[object.uid] = object;
}


UPDATE

It’s also possible to use an object as an index in addition to the array.

This way you’ve got fast lookups and also a working array:

var arr = [],
arrIndex = {};
addOrReplace({uid: 1, name: "bla", description: "cucu"});
addOrReplace({uid: 2, name: "smth else", description: "cucarecu"});
addOrReplace({uid: 1, name: "bli", description: "cici"});
function addOrReplace(object) {
var index = arrIndex[object.uid];
if(index === undefined) {
index = arr.length;
arrIndex[object.uid] = index;
}
arr[index] = object;
}

Take a look at the jsfiddle-demo (an object-oriented solution you’ll find here)