Reputation: 1186
I have this array of objects
var source = [
{id: 1, label: "one"},
{id: 2, label: "two"},
{id: 3, label: "three"}
];
I need to add an item or substitute it if it has the same id
var new_sub = {id: 1, label: "new label for one"};
var new_add = {id: 4, label: "four"};
source = myFunc(new_sub);
source = myFunc(new_add);
function myFunc(obj) {
return (source.findIndex(x => x.id === obj.id) === -1) ?
source.concat(obj) : source.map((item) => {
return (item.id === obj.id) ? obj : item;
});
}
This code works perfectly, but is there a better way to do this? You can check my code to this snippit:
var source = [
{id: 1, label: "one"},
{id: 2, label: "two"},
{id: 3, label: "three"}
];
var new_sub = {id: 1, label: "new label for one"};
var new_add = {id: 4, label: "four"};
source = myFunc(new_sub);
source = myFunc(new_add);
function myFunc(obj) {
return (source.findIndex(x => x.id === obj.id) === -1) ?
source.concat(obj) : source.map((item) => {
return (item.id === obj.id) ? obj : item;
});
}
//PRINT
var html = "";
source.map((item) => {
html += "<li>" + item.id + " - " + item.label + "</li>";
});
$("#resp").html(html);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul id="resp">
</ul>
Upvotes: 4
Views: 114
Reputation:
function myFunc( o )
{
let i ;
if ( (i = source[0].indexOf(o.id)) < 0 )
{
source[0].push(o.id) ; source.push(o)
}
else
{
source[1 + i] = o
}
// return JSON.parse(JSON.stringify(source)) // new Array with primitives
return source // As reference
}
var source = [
[4, 1, 3, 2] // the trick here
, {id: 4, label: "four"}
, {id: 1, label: "one"}
, {id: 3, label: "three"}
, {id: 2, label: "two"}
];
var new_sub = {id: 1, label: "new label for one"};
var new_add = {id: 6, label: "six new label"};
source = myFunc(new_sub);
console.log("// => source after new sub", source);
source = myFunc(new_add);
console.log("// => source after new add", source);
Upvotes: 0
Reputation: 31712
function myFunc(obj) {
let i = source.findIndex(x => x.id === obj.id); // get the index
if(i === -1) sources.push(obj); // if there isn't any object that have the same id, then push this obj into the array
else sources[i] = obj; // if there is then replace it
return sources; // this won't be necessary the array get mutated so no need to store it back into sources (see note bellow)
}
Note: Your version of myFunc
creates a new array each time it is called. My version doesn't. But since you are storing the return value of myFunc
back into sources
, I guess creating a new array isn't needed (in my version you won't have to do sources = myFunc(...)
as the array sources
get mutated).
Older browsers support: (and actually better)
function myFunc(obj) {
for (var i = 0; i < sources.length && sources[i].id !== obj.id; i++) // stop when reaching the end of the array or when we find an object with the same id
; // empty loop (just using it to find the index)
sources[i] = obj; // i will be either the index of the found object (so it will be replaced by obj) or sources.length (so obj will be added to the array)
}
Upvotes: 1
Reputation: 138567
If you do this often (insert a few thousand elements) it may be better (concerning performance) to build up a hash table ( which has a lookup time of O(1) instead of O(n) for searching an array):
var source = [
{id: 1, label: "one"},
{id: 2, label: "two"},
{id: 3, label: "three"}
];
var hash = new Map(source.map((el,i)=>[el.id,i]));
function substitute(elem){
var i = hash.get(elem.id);
if(i !== undefined){
return source[i] = elem;
}
hash.set(elem.id,source.push(elem));
}
Upvotes: 0
Reputation: 1075925
You're making multiple passes over the array (one in findIndex
, then one in either concat
or map
), which is unnecessary. Just a single pass will do it:
function myFunc(a, obj) {
let found = false;
const result = a.map(e => {
if (!found && e.id === obj.id) {
found = true;
return obj;
} else {
return e;
}
});
if (!found) {
result.push(obj);
}
return result;
}
Note that I passed the source array into the function as an argument, so it doesn't have side-effects.
var source = [
{id: 1, label: "one"},
{id: 2, label: "two"},
{id: 3, label: "three"}
];
var new_sub = {id: 1, label: "new label for one"};
var new_add = {id: 4, label: "four"};
source = myFunc(source, new_sub);
source = myFunc(source, new_add);
console.log(source);
function myFunc(a, obj) {
let found = false;
const result = a.map(e => {
if (!found && e.id === obj.id) {
found = true;
return obj;
} else {
return e;
}
});
if (!found) {
result.push(obj);
}
return result;
}
Of course, if the array is small and you know that's the standard case, it doesn't really matter.
If you want to be concise at the expense of (in my view) abusing the ,
operator:
function myFunc(a, obj) {
let found = false;
const result = a.map(e => e.id === obj.id ? (found = true, obj) : e);
if (!found) {
result.push(obj);
}
return result;
}
Upvotes: 1