I have an array of object and I want to copy that array of object to another array while modifying some items, like copying id only by ascending order and copying only the value of trophies of basketball to trophies. How to do it?
const item = [{
"id": 33,
"name": "John"
"trophies": {
"basketball" : 2,
"baseball" : 5
},
"profile": "profile/212"
}
{
"id": 12,
"name": "Michael"
"trophies": {
"basketball" : 6,
"baseball" : 7
},
"profile": "profile/341"
}
]
I want the above array of object after copying to look something like
const item2 = [{
"id": 12,
"name": "Michael"
"trophies": 6,
"profile": "http://collegeprofile.com/profile/341"
},
{
"id": 33,
"name": "John"
"trophies": 2,
"profile": "http://collegeprofile.com/profile/212"
}
]
You can sort by id ascending order using Array.prototype.sort
And map basketball value to trophies using Array.prototype.map.
const item = [{
"id": 33,
"name": "John",
"trophies": {
"basketball": 2,
"baseball": 5
},
"profile": "profile/212"
}, {
"id": 12,
"name": "Michael",
"trophies": {
"basketball": 6,
"baseball": 7
},
"profile": "profile/341"
}];
const output = item.sort((a, b) => (a.id - b.id)).map((item) => ({
...item,
trophies: item.trophies.basketball,
profile: "http://collegeprofile.com/" + item.profile
}));
console.log(output);
Related
This question already has answers here:
JS (ES6): Filter array based on nested array attributes
(7 answers)
Filtering array of objects with arrays based on nested value
(8 answers)
Closed 10 days ago.
I need to return the object which hobbies is reading, below is my sample scenario
[
{
"id": 1,
"name": "john",
"hobbies": [
{
"id": 1,
"name": "playing"
}
]
},
{
"id": 3,
"name": "peter",
"hobbies": [
{
"id": 3,
"name": "reading"
}
]
}
]
// Expected Output:
[
{
"id": 3,
"name": "peter",
"hobbies": [
{
"id": 3,
"name": "reading"
}
]
}
]
I use filter() and find() method however i couldn't loop it inside hobbies array
Use Array#filter in conjunction with Array#some.
let arr = [ { "id": 1, "name": "john", "hobbies": [ { "id": 1, "name": "playing" } ] }, { "id": 2, "name": "mary", "hobbies": [ { "id": 2, "name": "cleaning" } ] }, { "id": 3, "name": "peter", "hobbies": [ { "id": 3, "name": "reading" } ] } ];
let res = arr.filter(x => x.hobbies.some(h => h.name === 'reading'));
console.log(res);
Use Array.prototype.filter method to filter the outer array and Array.prototype.some method to check if an object in the inner hobbies array has a name property of "reading"
let people = [ { "id": 1, "name": "john", "hobbies": [ { "id": 1, "name": "playing" } ] }, { "id": 2, "name": "mary", "hobbies": [ { "id": 2, "name": "cleaning" } ] }, { "id": 3, "name": "peter", "hobbies": [ { "id": 3, "name": "reading" } ] } ];
let readingPerson = people.filter(person =>
person.hobbies.some(hobby => hobby.name === "reading")
)[0];
console.log(readingPerson);
I need: for each property id in first array that equals id property in second array change property liked in first array from false to true. So very specifically, looking at second array we can conclude that in first array objects with id value 34, 31 and 35 will now have liked:true. How to accomplish such code?
First array:
Array [
Object {
"Aw8AUj1mPkON1Fd1s6LhkNETHfb2": "liked",
"avatar": null,
"hugCount": 2,
"id": 35,
"liked": false,
"name": "fhfdhdhf",
"text": "Yoho",
"timestamp": 1610471860157,
"uid": "FOgepuJqxXfkHxI8OAV2KMWodXo1",
},
Object {
"avatar": null,
"hugCount": 1,
"id": 34,
"liked": false,
"mood": 2,
"name": "fhfdhdhf",
"text": "I'm fine today.",
"timestamp": 1607943705709,
"uid": "FOgepuJqxXfkHxI8OAV2KMWodXo1",
},
Object {
"avatar": "https://firebasestorage.googleapis.com/v0/b/eleph-6fee9.appspot.com/o/avatars%2Fm2OnHQiDuVM3Bp40Sc2ikqqmiQz2?alt=media&token=a2d66c27-ec63-422d-a3e4-76fcf7a12134",
"hugCount": 3,
"id": 33,
"liked": false,
"mood": 3,
"name": "Matko",
"text": "evotv",
"timestamp": 1606350804169,
"uid": "m2OnHQiDuVM3Bp40Sc2ikqqmiQz2",
}]
and this first array goes on for long but I closed it here cause its enough to show it
Second Array:
Array [
Object {
"id": 34,
"userHandle": "Aw8AUj1mPkON1Fd1s6LhkNETHfb2",
},
Object {
"id": 31,
"userHandle": "Aw8AUj1mPkON1Fd1s6LhkNETHfb2",
},
Object {
"id": 35,
"userHandle": "Aw8AUj1mPkON1Fd1s6LhkNETHfb2",
},
]
You can use Array.prototype.some() to test if any objects in the second array have matching ids and assign the returned boolean to liked.
const
arr1 = [{ "Aw8AUj1mPkON1Fd1s6LhkNETHfb2": "liked", "avatar": null, "hugCount": 2, "id": 35, "liked": false, "name": "fhfdhdhf", "text": "Yoho", "timestamp": 1610471860157, "uid": "FOgepuJqxXfkHxI8OAV2KMWodXo1", }, { "avatar": null, "hugCount": 1, "id": 34, "liked": false, "mood": 2, "name": "fhfdhdhf", "text": "I'm fine today.", "timestamp": 1607943705709, "uid": "FOgepuJqxXfkHxI8OAV2KMWodXo1", }, { "avatar": "https://firebasestorage.googleapis.com/v0/b/eleph-6fee9.appspot.com/o/avatars%2Fm2OnHQiDuVM3Bp40Sc2ikqqmiQz2?alt=media&token=a2d66c27-ec63-422d-a3e4-76fcf7a12134", "hugCount": 3, "id": 33, "liked": false, "mood": 3, "name": "Matko", "text": "evotv", "timestamp": 1606350804169, "uid": "m2OnHQiDuVM3Bp40Sc2ikqqmiQz2", }],
arr2 = [{ "id": 34, "userHandle": "Aw8AUj1mPkON1Fd1s6LhkNETHfb2", }, { "id": 31, "userHandle": "Aw8AUj1mPkON1Fd1s6LhkNETHfb2", }, { "id": 35, "userHandle": "Aw8AUj1mPkON1Fd1s6LhkNETHfb2", },]
arr1.forEach(o => o.liked = arr2.some(({ id }) => o.id === id));
console.log(arr1)
This should get you the answer in O(n).
First array = va
Second array = ta
function test(arr1, arr2){
let em = {};
arr2.forEach(({id}) => em[id] = 1);
return arr1.map(el => {
em[el.id] ? el.liked = true : null;
return el;
})
}
va = test(va, ta);
const arr1 = [{id: 1, liked: false}, {id: 2, liked: false}, {id: 3, liked: false}];
const arr2 = [{id: 1}, {id: 3}];
arr1.forEach(element1 => {
element1.liked = arr2.some((element2) => {
return element1.id === element2.id;
});
});
Explanation:
Iterate through each array element in "arr1" (array of objects), then assign the "element1.liked" with the value returns from 'some' method. that method actually iterate through each element in "arr2" and assign it to element2 (similar to forEach) and return boolean value if the id's are equal, same boolean value that assigns to element1.liked. Hope that understandable and accurate enough.
I came up with an example from another topic which can filter nested array from another array where filter values stored.
Interestingly when there is single element in array,it doesnt work well.
const data = [
{
"guid": "j5Dc9Z",
"courses": [
{
"id": 3,
"name": "foo"
}
]
},
{
"guid": "a5gdfS",
"courses": [
{
"id": 1,
"name": "bar"
},
{
"id": 3,
"name": "foo"
}
]
},
{
"guid": "jHab6i",
"courses": [
{
"id": 7,
"name": "foobar"
}
]
}
];
const courses = [3];
const r = data.filter(d => d.courses.every(c => courses.includes(c.id)));
console.log(r);
in case of my example,we are supposed to see two 3 but instead it gives us first one.How can I filter this nested array with multiple values or single?
You are asking for ALL/EVERY object to have id == 3 here, but what you want is to have ANY/SOME of the objects to have id == 3, like here:
const data = [{
"guid": "j5Dc9Z",
"courses": [{
"id": 3,
"name": "foo"
}]
},
{
"guid": "a5gdfS",
"courses": [{
"id": 1,
"name": "bar"
}, {
"id": 3,
"name": "foo"
}]
}, {
"guid": "jHab6i",
"courses": [{
"id": 7,
"name": "foobar"
}]
}
];
const courses = [3];
const r = data
.filter(d => d.courses.some(c => courses.includes(c.id)))
.map(d => ({ ...d, courses: d.courses.filter(c => courses.includes(c.id))
}));
console.log(r);
If you want to find all items in the data that contain all of the ids found in the const courses, then you need to invert your filtering.
const data = [
{"guid": "j5Dc9Z", "courses": [{"id": 3, "name": "foo"}]},
{"guid": "a5gdfS", "courses": [{"id": 1, "name": "bar"}, {"id": 3, "name": "foo"}]},
{"guid": "jHab6i", "courses": [{"id": 7, "name": "foobar"}]}
];
const courses = [3];
const r = data.filter(d => courses.every(courseId => d.courses.find(({
id
}) => courseId === id)));
console.log(r);
I have three arrays.
1. Existing viewers array - existingViewers
New viewers array - newViewers
Permitted Viewers array - permittedViewers
permittedViewers is used for rendering the drop-down. And I wish to filter the newViewers and existingViewers entries from the permittedViewers.
I am doing this as three steps. And I am afraid this is not the optimized way. Can someone suggest the ideal way of doing this?
The expected result is
[
{
"id": 4,
"name": "name4"
},
{
"id": 5,
"name": "name5"
},
{
"id": 6,
"name": "name6"
}
]
let existingViewers = [{
"viewerId": 1,
"name": "name1"
},
{
"viewerId": 2,
"name": "name2"
}
],
newViewers = [
{
"viewerId": 3,
"name": "name3"
}
],
permittedViewers = [{
"id": 1,
"name": "name1"
},
{
"id": 2,
"name": "name2"
},
{
"id": 3,
"name": "name3"
},
{
"id": 4,
"name": "name4"
},
{
"id": 5,
"name": "name5"
},
{
"id": 6,
"name": "name6"
}
]
let grouped = [...existingViewers, ...newViewers]
let viewerFilter = grouped.map(viewer => { return viewer.viewerId; });
let filteredPermittedViewers = permittedViewers.filter(viewer => !viewerFilter.includes(viewer.id));
console.log(filteredPermittedViewers)
I'd make a Set of the ids of the first two arrays, and then filter the third by whether the set includes the id. (Sets have O(1) lookup time)
let existingViewers=[{"viewerId":1,"name":"name1"},{"viewerId":2,"name":"name2"}],newViewers=[{"viewerId":3,"name":"name3"}],permittedViewers=[{"id":1,"name":"name1"},{"id":2,"name":"name2"},{"id":3,"name":"name3"},{"id":4,"name":"name4"},{"id":5,"name":"name5"},{"id":6,"name":"name6"}];
const ids = new Set([...existingViewers, ...newViewers].map(({ viewerId }) => viewerId));
const output = permittedViewers.filter(({ id }) => !ids.has(id));
console.log(output);
You can compress all three statements into a single statement -- just replace the variable name with the statement that creates it:
let existingViewers = [{
"viewerId": 1,
"name": "name1"
},
{
"viewerId": 2,
"name": "name2"
}
],
newViewers = [
{
"viewerId": 3,
"name": "name3"
}
],
permittedViewers = [{
"id": 1,
"name": "name1"
},
{
"id": 2,
"name": "name2"
},
{
"id": 3,
"name": "name3"
},
{
"id": 4,
"name": "name4"
},
{
"id": 5,
"name": "name5"
},
{
"id": 6,
"name": "name6"
}
]
let filteredPermittedViewers = permittedViewers.filter(viewer => ! [...existingViewers, ...newViewers].map(viewer => viewer.viewerId).includes(viewer.id));
console.log(filteredPermittedViewers)
I have an array of objects that looks like this
[{
"name": "Agile Process",
"id": 27,
"score": 3,
"source": "Self"
},{
"name": "Agile Process",
"id": 27,
"score": 4,
"source": "Trainer"
},{
"name": "2 & 3 Tier Architecture",
"id": 37,
"score": 4,
"source": "Self"
},{
"name": "2 & 3 Tier Architecture",
"id": 37,
"score": 5,
"source": "Trainer"
}]
I want to be able to produce something like this, I have been trying hard but I do not seems to get a hang of it.
[
{
"name": "Agile Process",
"id": 7,
"data": [
{
"score": 3,
"source": "Self"
},{
"score": 4,
"source": "Trainer"
}
]
},
{
"name": "2 & 3 Tier Architecture",
"id": 37,
"data": [
{
"score": 4,
"source": "Self"
},{
"score": 5,
"source": "Trainer"
}]
}
];
How do I go about solving this problem?
One possible approach:
_.values(_.reduce(arr, function(acc, el) {
var id = el.id;
if (!acc.hasOwnProperty(id)) {
acc[id] = _.pick(el, 'id', 'name');
acc[id].data = [];
}
acc[id].data.push(_.pick(el, 'score', 'source'));
return acc;
}, {}));
Demo. It's a common method when you need to group things up.
Here's a pure javascript solution: use reduce method on the initial array using as the accumulator the result array (empty at first) which will store the transformed data. And as reduce method loops through the items of the initial array, check if the result array contains an element with id of the current item. If so, then just add new data to it, else create a new item in the result array.
var data = [{
"name": "Agile Process",
"id": 27,
"score": 3,
"source": "Self"
},{
"name": "Agile Process",
"id": 27,
"score": 4,
"source": "Trainer"
},{
"name": "2 & 3 Tier Architecture",
"id": 37,
"score": 4,
"source": "Self"
},{
"name": "2 & 3 Tier Architecture",
"id": 37,
"score": 5,
"source": "Trainer"
}];
var newData = [];
newData = data.reduce(function(acc, current) {
var existingArr = acc.filter(function(x) { return x.id === current.id });
if(existingArr.length === 0) {
acc.push({ name: current.name, id: current.id, data: [{ score: current.score, source: current.source }] });
}
else {
existingArr[0].data.push({ score: current.score, source: current.source });
}
return acc;
}, newData);
This version uses groupBy to group the items by id and then maps across each grouping to create the required object:
var groupToItem = function(items){
return {
id: items[0].id,
name: items[0].name,
data: _.map(items, function(item){
return _.pick(item, 'score', 'source');
})
}
}
var result = _.chain(data)
.groupBy('id')
.map(groupToItem)
.value();
Plain Javascript solution, only working for your specific data structure though:
function groupObjectsById(array){
var output = [];
var ids = [];
for(var i = 0; i < array.length; i++){
var current = array[i];
if(ids.indexOf(current.id) > -1){
var objInOutput = output.filter(function(obj){
if(obj.id === current.id){
return obj;
}
})[0];
var dataObj = { score: current.score, source: current.source};
objInOutput.data.push(dataObj);
}else{
var outputObject = {name: current.name, id: current.id};
outputObject.data = [{ score: current.score, source: current.source}];
output.push(outputObject);
ids.push(current.id);
}
}
return output;
}