How to edit object array? - javascript

I want to edit JavaScript object.
I have an JavaScript object like this
data_without_id = [
0: {id: 1, name: "Mary", age: null}
1: {id: 2, name: "Bob", age: 33}
2: {id: 1, name: "Kelly", age: 40}
]
I want to convert this object into this
data_without_id = [
0: {id: 1, name: "Kelly", age: 40}
1: {id: 2, name: "Bob", age: 33}
]
What I need to do is:
Group by id
Get latest value.
I tried using Array.prototype.reduce(), but I can't get the result I need...

Using the function reduce would be as follow:
The function reduce for grouping and the function Object.values for extracting the values.
let data_without_id = [ { id: 1, name: "Mary", age: null }, { id: 2, name: "Bob", age: 33 }, { id: 1, name: "Kelly", age: 40 }],
result = Object.values(data_without_id.reduce((a, {id, name, age}) => {
a[id] = {id, name, age};
return a;
}, Object.create(null)));
console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }

You could use .reduce by making the accumulator an object that has keys of the id. This way you can overwrite any previously seen objects which had the same id, and then use Object.values to get your array of objects:
const data_without_id = [{id: 1, name: "Mary", age: null}, {id: 2, name: "Bob", age: 33}, {id: 1, name: "Kelly", age: 40}],
res = Object.values(data_without_id.reduce((acc, obj) =>
(acc[obj.id] = obj, acc)
, {}));
console.log(res);

You could just simply use a for/of loop to create a copy of the data where the last object with a particular id will always be the object returned in the output data. This avoids the "grouping" part of the code but still returns the correct data.
const data_without_id = [
{ id: 1, name: "Mary", age: null },
{ id: 2, name: "Bob", age: 33 },
{ id: 1, name: "Kelly", age: 40 }
];
function lastId(arr) {
const out = [];
for (let obj of arr) {
// If you don't create a copy of each object the returned
// data will simply be contain _references_ to the original
// data. Changes in the original data will be reflected
// in the returned data
out[obj.id - 1] = { ...obj };
}
return out;
}
const lastIds = lastId(data_without_id);
console.log(lastIds);

Related

Build an array of arrays from an array using REDUCE in javascript [duplicate]

This question already has answers here:
How to get all properties values of a JavaScript Object (without knowing the keys)?
(25 answers)
Closed 10 months ago.
Input data
const users = [{id: 1, name: 'Madou', age: 37},
{id: 2, name: 'Fatoumata', age: 33},
{id: 3, name: 'Amadou', age: 31}];
Output
[ [ 1, 'Madou', 37 ], [ 2, 'Fatoumata', 33 ], [ 3, 'Amadou', 31 ] ]
I implemented this:
const _data = users.map((item) => {
return Object.keys(item).map((value) => item[value]);
});
console.log(_data);
But I want to use REDUCE instead, but I don't have any how to do it
You can use Array.map() as follows:
const users = [{id: 1, name: 'Madou', age: 37},
{id: 2, name: 'Fatoumata', age: 33},
{id: 3, name: 'Amadou', age: 31}];
const result = users.map(o => Object.values(o));
console.log(result);
const _data = users.reduce((acc, { id, name, age }) => {
acc.push([id, name, age]);
return acc;
}, []);

Is there a cleaner way to add a new property with unique values to an array

I'm just learning js now (late to the party I know) and I have the following code and I was wondering if it could be written in a cleaner/simpler way?
Also, ideally, instead of using "if (obj.id === 1)" I would like to iterate through the array and add age based on the sequence i.e. [0] would become '32' and so on.
const students = [ // Three objects, each with four properties
{
id: 1,
name: 'Mark',
profession: 'Developer',
skill: 'JavaScript'
},
{
id: 2,
name: 'Ariel',
profession: 'Developer',
skill: 'HTML'
},
{
id: 3,
name: 'Jason',
profession: 'Designer',
skill: 'CSS'
},
];
const studentsWithAge = students.map(obj => {
if (obj.id === 1) {
return {...obj, age: '32'};
} else if (obj.id === 2) {
return {...obj, age: '26'};
} else if (obj.id === 3) {
return {...obj, age: '28'};
}
return obj;
});
console.log(studentsWithAge);
// output
// [
// {
// id: 1,
// name: 'Mark',
// profession: 'Developer',
// skill: 'JavaScript',
// age: '32'
// },
// {
// id: 2,
// name: 'Ariel',
// profession: 'Developer',
// skill: 'HTML',
// age: '26'
// },
// {
// id: 3,
// name: 'Jason',
// profession: 'Designer',
// skill: 'CSS',
// age: '28'
// }
// ]
You can map the array into the object like so:
const ages = ['32', '26', '28'];
const studentsWithAge = students.map(obj => { ...obj, age: ages[obj.id-1] });
You could create an ages array and use the index to map the value to the corresponding object.
const students = [ // Three objects, each with four properties
{
id: 1,
name: 'Mark',
profession: 'Developer',
skill: 'JavaScript'
},
{
id: 2,
name: 'Ariel',
profession: 'Developer',
skill: 'HTML'
},
{
id: 3,
name: 'Jason',
profession: 'Designer',
skill: 'CSS'
},
];
const ages = [32, 26, 28];
const result = students.map((s, i) => {
return { ...s, age: ages[i] }
});
console.log(result);
Your code is true, another way to add ages by the id is the following code. Just use ids as object key and age as value.
The following code check if id exists in the ages const then add it to the studentsWithAge. It works exactly like your code.
const ages = {1: '32', 2: '26', 3: '28'};
const studentsWithAge = students.map(obj => {
if(ages[obj.id]) obj.age = ages[obj.id];
return obj;
});
But if you're sure all ids have age value simpler code like this could be used:
const ages = {1: '32', 2: '26', 3: '28'};
const studentsWithAge = students.map(obj => ({...obj, age: ages[obj.id]}));
The solution depends on how you store the ages data. Here's an example if you keep the ages data in an array of objects, just like you keep the students data.
This approach is easily extended, you can add any other fields related to the student to the object.
students = [
{id: 1,name: 'Mark',profession: 'Developer',skill: 'JavaScript'},
{id: 2,name: 'Ariel',profession: 'Developer',skill: 'HTML'},
{id: 3,name: 'Jason',profession: 'Designer',skill: 'CSS'}];
extraInfo = [{id: 1, age:32}, {id:2, age: 26}, {id:3, age: 33}];
const result = students.map((s)=>
({ ...s, ...extraInfo.find((a) => a.id === s.id) })
);
console.log(result);
.as-console-wrapper{min-height: 100%!important; top: 0}

How to add property to json file with map function?

Hello I m trying to map through a json file and add a new property to every object in it.
DATA.JSON
const arr = [
{
index: 0,
name: "John",
hair: "Brown",
},
{
index: 1,
name: "Bob",
hair: "Blonde",
},
];
APP.JS
const data = require("./data.json");
const items = data.map((item) => {
return ????
});
I want to map through the array, and add a "age" property to every index with a value of 30 or even just an empty value would be ok. with result something like this:
RESULT
const a =
[
{
index: 0,
name: "John",
hair: "Brown",
age: 30
},
{
index: 1,
name: "Bob",
hair: "Blonde",
age: 30
},
];
const arr = [
{
index: 0,
name: "John",
hair: "Brown",
},
{
index: 1,
name: "Bob",
hair: "Blonde",
},
];
const result = arr.map((obj) => {
return { ...obj, age: 30 };
});
console.log(result);
You can also make it one-liner
const result = arr.map((obj) => ({ ...obj, age: 30 }));
If you want to print only hair of each index then
const arr = [
{
index: 0,
name: "John",
hair: "Brown",
},
{
index: 1,
name: "Bob",
hair: "Blonde",
},
];
const result = arr.map((obj) => {
return { ...obj, age: 30 };
});
const hairs = result.map((o) => o.hair);
console.log(hairs); // Printing as an array
console.log(hairs.toString()); // Printing as comma separated value
Hello you could do something like this:
const data = [
{
index:0,
name: "John",
hair: "Brown",
},
{
index:1,
name: "Bob",
hair: "Blonde",
},
];
const newData = data.map(item => ({
...item,
newProp: 'hello world',
}));
// Print whole data:
console.log(newData);
// Filter specific properties
const hair = newData.map(item => item['hair'])
console.log('only hair ->', hair);
Side note, you don't need the index property in the object since you can get it while looping.
map(currentItem, index) Docs
If you want to print specific properties of the object you can do as such:
console.log(newData.map(item => item['hair']));

Javascript filter array based on another array of object

I am trying to merge the two arrays based on Arr1 values. If the array 2 doesn't has the respective value in array1, it should return as empty object with values. Below are the two arrays:
Arr1 = [{
name: "raj",
age: 20
}, {
name: "ravi",
age: 40
}];
Arr2 = ['raj', 'ravi', 'arnold'];
Javascript Code is,
let result = Arr1.filter(o1 => Arr2.some(o2 => o2 === o1.name));
I am getting the result as below,
result = [{
name: "raj",
age: 20
}, {
name: "ravi",
age: 40
}];
But expected array should be,
[{
name: "raj",
age: 20
}, {
name: "ravi",
age: 40
}, {
name: "arnold",
age: null,
available: no
}];
Any suggestions?
You can use Array#map along with Array#find to obtain your expected result.
let Arr1 = [{
name: "raj",
age: 20
}, {
name: "ravi",
age: 40
}];
let Arr2 = ['raj', 'ravi', 'arnold'];
let result = Arr2.map(x=>
Arr1.find(({name})=>name===x)??{name:x,age:null,available: 'no'}
);
console.log(result);
I suggest a different approach and take an object for the given data and map the wanted names for eithe the given data or a new object.
This approach has a better big O, becaus it take a hash table and works fast for great data.
const
array1 = [{ name: "raj", age: 20 }, { name: "ravi", age: 40 }],
array2 = ['raj', 'ravi', 'arnold'],
data = array1.reduce((r, o) => (r[o.name] = o, r), {}),
result = array2.map(name => data[name] || { name, age: null, available: 'no' });
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Iterating and filtering with ES6/lodash

We have an array of objects like:
const persons = [{
name: "john",
age: 23
}, {
name: "lisa",
age: 43
}, {
name: "jim",
age: 101
}, {
name: "bob",
age: 67
}];
And an array of a attribute values of the objects in object
const names = ["lisa", "bob"]
How can we find persons with name in the names array using es6, like:
const filteredPersons = [{
name: "lisa",
age: 43
}, {
name: "bob",
age: 67
}];
ES6
Use filter function with predicate and in it check the existence of the name in the names array.
const persons = [
{name: "john", age:23},
{name: "lisa", age:43},
{name: "jim", age:101},
{name: "bob", age:67}
];
const names = ["lisa", "bob"];
const filtered = persons.filter(person => names.includes(person.name));
console.log(filtered);
You can use filter() and inlcudes() to get required result.
DEMO
const persons = [{
name: "john",
age: 23
}, {
name: "lisa",
age: 43
}, {
name: "jim",
age: 101
}, {
name: "bob",
age: 67
}];
const names = ["lisa", "bob"];
console.log(persons.filter(({
name
}) => names.includes(name)))
.as-console-wrapper { max-height: 100% !important; top: 0; }
I would suggest to use indexOf as includes does not work in IE browser. Also, using {name} works as Destructuring assignment that will hold the value of name property of the object.
const persons = [{
name: "john",
age: 23
}, {
name: "lisa",
age: 43
}, {
name: "jim",
age: 101
}, {
name: "bob",
age: 67
}];
const names = ["lisa", "bob"];
console.log(persons.filter(({name}) => names.indexOf(name) !== -1))
lodash
You can try following
const persons = [{name: "john", age: 23},
{name: "lisa",age: 43},
{name: "jim", age: 101},
{name: "bob",age: 67}];
const names = ["lisa", "bob"]
const filteredPersons = _.filter(persons, function(person) {
return _.indexOf(names, person.name) !== -1;
});
console.log(filteredPersons);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.js"></script>
In case you want to perform it in n complexity, here is a way to do it:
Create a map with key as person's name and value as person's object.
Map the criteria array and extract the person objects from the map create in step 1.
Here is a working demo:
const persons = [{
name: "john",
age: 23
}, {
name: "lisa",
age: 43
}, {
name: "jim",
age: 101
}, {
name: "bob",
age: 67
}];
const names = ["lisa", "bob"];
const map = persons.reduce((acc, item) => {
acc[item.name] = item;
return acc;
}, {});
const result = names.map(name => map[name]);
console.log(result);
Note: This solution assumes that only unique person names are in the source array. It needs to be tweaked to handle duplicates.
See Closures, Set, and Array.prototype.filter() for more info.
// Input.
const persons = [{name: "john",age: 23}, {name: "lisa",age: 43}, {name: "jim",age: 101}, {name: "bob",age: 67}]
const names = ["lisa", "bob"]
// Filter.
const filter = (A, B) => (s => A.filter(x => s.has(x.name)))(new Set(B))
// Output.
const output = filter(persons, names)
// Proof.
console.log(output)

Categories

Resources