You can use Array#map with Array#find.
arr1.map(obj => arr2.find(o => o.id === obj.id) || obj);
Show code snippet
var arr1 = [{
id: '124',
name: 'qqq'
}, {
id: '589',
name: 'www'
}, {
id: '45',
name: 'eee'
}, {
id: '567',
name: 'rrr'
}];
var arr2 = [{
id: '124',
name: 'ttt'
}, {
id: '45',
name: 'yyy'
}];
var res = arr1.map(obj => arr2.find(o => o.id === obj.id) || obj);
console.log(res);
Run code snippetEdit code snippet Hide Results Copy to answer Expand
Here, arr2.find(o => o.id === obj.id) will return the element i.e. object from arr2 if the id is found in the arr2. If not, then the same element in arr1 i.e. obj is returned.
You can use Array#map with Array#find.
arr1.map(obj => arr2.find(o => o.id === obj.id) || obj);
Show code snippet
var arr1 = [{
id: '124',
name: 'qqq'
}, {
id: '589',
name: 'www'
}, {
id: '45',
name: 'eee'
}, {
id: '567',
name: 'rrr'
}];
var arr2 = [{
id: '124',
name: 'ttt'
}, {
id: '45',
name: 'yyy'
}];
var res = arr1.map(obj => arr2.find(o => o.id === obj.id) || obj);
console.log(res);
Run code snippetEdit code snippet Hide Results Copy to answer Expand
Here, arr2.find(o => o.id === obj.id) will return the element i.e. object from arr2 if the id is found in the arr2. If not, then the same element in arr1 i.e. obj is returned.
There is always going to be a good debate on time vs space, however these days I've found using space is better for the long run.. Mathematics aside let look at a one practical approach to the problem using hashmaps, dictionaries, or associative array's whatever you feel like labeling the simple data structure..
var marr2 = new Map(arr2.map(e => [e.id, e]));
arr1.map(obj => marr2.has(obj.id) ? marr2.get(obj.id) : obj);
I like this approach because though you could argue with an array with low numbers you are wasting space because an inline approach like @Tushar approach performs indistinguishably close to this method. However I ran some tests and the graph shows how performant in ms both methods perform from n 0 - 1000. You can decide which method works best for you, for your situation but in my experience users don't care to much about small space but they do care about small speed.

Here is my performance test I ran for source of data
var n = 1000;
var graph = new Array();
for( var x = 0; x < n; x++){
var arr1s = [...Array(x).keys()];
var arr2s = arr1s.filter( e => Math.random() > .5);
var arr1 = arr1s.map(e => {return {id: e, name: 'bill'}});
var arr2 = arr2s.map(e => {return {id: e, name: 'larry'}});
// Map 1
performance.mark('p1s');
var marr2 = new Map(arr2.map(e => [e.id, e]));
arr1.map(obj => marr2.has(obj.id) ? marr2.get(obj.id) : obj);
performance.mark('p1e');
// Map 2
performance.mark('p2s');
arr1.map(obj => arr2.find(o => o.id === obj.id) || obj);
performance.mark('p2e');
graph.push({ x: x, r1: performance.measure('HashMap Method', 'p1s', 'p1e').duration, r2: performance.measure('Inner Find', 'p2s','p2e').duration});
}
Let's say I have an array called data and it contains the following:
data: [
{
id: 100,
name: "something",
code_block: "x\ny\nz\na\nresult:touchdown\nasd\n"
},
{
id: 200,
name: "somethingElse",
code_block: "a\nb\nc\nd\nresult:touchdown\nasd\n"
}
]What I'm trying to do is iterate through the code_block property to extract out a string (result:touchdown) and replace the original value of code_block with that string. The problem is I'm not sure how I can perform the array methods like .map and such and still carry over the id and name properties.
Would you guys recommend that I make a shallow copy of the data object, iterate through code_block, and then replace that property on the original data object with the new array? Is there even a way to do this, or is there a better approach to what I'm doing here?
Thanks in advance for all your help!
angular - Replacing value in an Array in typescript - Stack Overflow
Replacing objects in array
angular - Typescript - replace value in an array object - Stack Overflow
Replace array in object with object in TypeScript - Stack Overflow
You're not using assignment. As Doc explains, forEach run the provided function for each element, and your function simply return a boolean if x.DataSource exist, a string otherwise.
If your goal is to change your array you can either modify your function with an assignment:
this.localData.forEach(x => {
x.DataSource = x.DataSource ? '' || 'XXX' : 'MyVAL'
});
or simply use the map function
this.localData = this.localData.map( item => {
item.DataSource = item.DataSource ? '' || 'XXX' : 'MyVAL'
return item;
});
Clarification: in your code line
this.localData.forEach(x => x.DataSource ? '' || 'XXX' : 'MyVAL');
the ternary operator is gonna return 'MyVAL' if x.DataSource is undefined or the empty string, and always 'XXX' if all the other cases. If i get it right, you want to do something like:
x.DataSource && x.DataSource !== 'XXX' ? 'MyVAL' : x.DataSource;
which can be read as: if DataSource is evaluated and it's different from 'XXX' assign 'MyVal', keep it as it is otherwise.
EDIT: clarification
try following way:
this.localData.forEach(x => (!x.DataSource || x.DataSource === 'XXX') ? 'MyVAL' : x.DataSource);
Where
!x.DataSource means x.DataSource === ''
You can use Array#map with Array#find.
arr1.map(obj => arr2.find(o => o.id === obj.id) || obj);
Show code snippet
var arr1 = [{
id: '124',
name: 'qqq'
}, {
id: '589',
name: 'www'
}, {
id: '45',
name: 'eee'
}, {
id: '567',
name: 'rrr'
}];
var arr2 = [{
id: '124',
name: 'ttt'
}, {
id: '45',
name: 'yyy'
}];
var res = arr1.map(obj => arr2.find(o => o.id === obj.id) || obj);
console.log(res);
Run code snippetEdit code snippet Hide Results Copy to answer Expand
Here, arr2.find(o => o.id === obj.id) will return the element i.e. object from arr2 if the id is found in the arr2. If not, then the same element in arr1 i.e. obj is returned.
There is always going to be a good debate on time vs space, however these days I've found using space is better for the long run.. Mathematics aside let look at a one practical approach to the problem using hashmaps, dictionaries, or associative array's whatever you feel like labeling the simple data structure..
var marr2 = new Map(arr2.map(e => [e.id, e]));
arr1.map(obj => marr2.has(obj.id) ? marr2.get(obj.id) : obj);
I like this approach because though you could argue with an array with low numbers you are wasting space because an inline approach like @Tushar approach performs indistinguishably close to this method. However I ran some tests and the graph shows how performant in ms both methods perform from n 0 - 1000. You can decide which method works best for you, for your situation but in my experience users don't care to much about small space but they do care about small speed.

Here is my performance test I ran for source of data
var n = 1000;
var graph = new Array();
for( var x = 0; x < n; x++){
var arr1s = [...Array(x).keys()];
var arr2s = arr1s.filter( e => Math.random() > .5);
var arr1 = arr1s.map(e => {return {id: e, name: 'bill'}});
var arr2 = arr2s.map(e => {return {id: e, name: 'larry'}});
// Map 1
performance.mark('p1s');
var marr2 = new Map(arr2.map(e => [e.id, e]));
arr1.map(obj => marr2.has(obj.id) ? marr2.get(obj.id) : obj);
performance.mark('p1e');
// Map 2
performance.mark('p2s');
arr1.map(obj => arr2.find(o => o.id === obj.id) || obj);
performance.mark('p2e');
graph.push({ x: x, r1: performance.measure('HashMap Method', 'p1s', 'p1e').duration, r2: performance.measure('Inner Find', 'p2s','p2e').duration});
}
Some notes:
With
map, you return the object you want the new array to contain. Assigning to the parameterejust changes the value of the parameter, which isn't retained anywhere.There's no need for
Object.assignthere, just create the object directly, so:const replaced = album.songs.map(e => { return { _id : e }; } );or the concise form:
const replaced = album.songs.map(e => ({ _id : e }) );Note that since we want to return an object created with an object initializer, and the
{in the initializer would start a function body, we wrap the value we want to return in().We can even take advantage of shorthand property notation if we change the name of the parameter to
_id:const replaced = album.songs.map(_id => ({ _id }) );
Live Example:
Show code snippet
const album = {songs: [1234545, 43524]};
const replaced = album.songs.map(_id => ({ _id }) );
console.log(replaced);
Run code snippetEdit code snippet Hide Results Copy to answer Expand
You don't assign to the function parameter, since it only exists for that function, and it's not like you're dereferencing a pointer.
Just return the object. An arrow function automatically returns its expression if you don't use curly braces to denote the body.
var songs = [1234545, 43524];
const replaced = songs.map(e => ({_id: e}));
console.log(replaced);
Run code snippetEdit code snippet Hide Results Copy to answer Expand
var index = items.indexOf(3452);
if (index !== -1) {
items[index] = 1010;
}
Also it is recommend you not use the constructor method to initialize your arrays. Instead, use the literal syntax:
var items = [523, 3452, 334, 31, 5346];
You can also use the ~ operator if you are into terse JavaScript and want to shorten the -1 comparison:
var index = items.indexOf(3452);
if (~index) {
items[index] = 1010;
}
Sometimes I even like to write a contains function to abstract this check and make it easier to understand what's going on. What's awesome is this works on arrays and strings both:
var contains = function (haystack, needle) {
return !!~haystack.indexOf(needle);
};
// can be used like so now:
if (contains(items, 3452)) {
// do something else...
}
Starting with ES6/ES2015 for strings, and proposed for ES2016 for arrays, you can more easily determine if a source contains another value:
if (haystack.includes(needle)) {
// do your thing
}
The Array.indexOf() method will replace the first instance. To get every instance use Array.map():
a = a.map(item => item == 3452 ? 1010 : item);
Of course, that creates a new array. If you want to do it in place, use Array.forEach():
a.forEach((item, i) => { if (item == 3452) a[i] = 1010; });
