Subset Json object in Javascript - javascript

Given an array of json object like this below, (the json object such as "name2" and "name4" will definitely have only one key-value)
[
{
abc: 123,
id: '18263322',
name: 'name1'
},
{ name: 'name2' },
{
abc: 456,
id: '18421634',
name: 'name3'
},
{ name: 'name4' }
]
How can I subset this so that I have two array of json objects:
[
{
abc: 123,
id: '18263322',
name: 'name1'
},
{
abc: 456,
id: '18421634',
name: 'name3'
}
]
and
[
{ name: 'name2' },
{ name: 'name4' }
]

You can use reduce here
const arr = [
{
abc: 123,
id: "18263322",
name: "name1",
},
{ name: "name2" },
{
abc: 456,
id: "18421634",
name: "name3",
},
{ name: "name4" },
];
const [single, multiple] = arr.reduce((acc, curr) => {
Object.keys(curr).length === 1 ? acc[0].push(curr) : acc[1].push(curr);
return acc;
},[[], []]
);
console.log(single);
console.log(multiple);
You can also do something like
const [single, multiple] = arr.reduce((acc, curr) => {
acc[Object.keys(curr).length === 1 ? 0 : 1].push(curr);
return acc;
},[[], []]);
using filter
const arr = [
{
abc: 123,
id: "18263322",
name: "name1",
},
{ name: "name2" },
{
abc: 456,
id: "18421634",
name: "name3",
},
{ name: "name4" },
];
const single = arr.filter((o) => Object.keys(o).length === 1);
const multiple = arr.filter((o) => Object.keys(o).length !== 1);
console.log(single);
console.log(multiple);

Related

How to change object value in array with objects with if/else in JS

I have an array with objects. I need to find item with current name and change it.
const example = [
{
id: '1234',
desc: 'sample1',
items: [
itemsName: [
{ id: 1, name: 'name1' },
{ id: 2, name: 'testItem2' }
],
id: 888,
]
},
{
id: '3456',
desc: 'sample2',
items: [
itemsName: [
{ id: 1, name: 'name2' },
{ id: 2, name: 'testItem3' }
],
id: 889,
]
},
I try to do in this way, but it's not working.
I get construction like (5) 
[Array(1), Array(1)]
instead of 
[{…}, {…}]
const findName = (name, changedName) => {
const result = example?.map((group) =>
group.items.map((group) =>
group.itemsName?.map((i) => {
if (i.name === name) return i.name === changedName;
return null;
})
)
);
}
findName('name1', 'name2')
let findName1 = (name, changedName) => {
const result = example?.map((group) =>
group.items.map((group) =>
group.itemsName?.map((i) => {
if (i.name === name) return i.name = changedName;
return null;
})
)
);
}
This will work with following object (your object declaration seems to be wrong)
const example = [
{
id: '1234',
desc: 'sample1',
items: [
{itemsName: [
{ id: 1, name: 'name1' },
{ id: 2, name: 'testItem2' }
],
id: 888,}
]
},
{
id: '3456',
desc: 'sample2',
items: [
{itemsName: [
{ id: 1, name: 'name2' },
{ id: 2, name: 'testItem3' }
],
id: 889,}
]
}]

How to compare two array of objects and return the not matching object?

obj1 is the original object and obj2 is the changed object. I want to get the key , value pair and the type of all the changed object inside obje2 array of objects.
So, I need something like this where if "name" or "id" value is different in obj2 return the object along with the type.
changedObj = [
{
type:"mobile",
name:"Temple Runs",
id:2259
},
{
type:"pc",
name:"Pubgs",
id:222
}
]
obj1 = [
{
type: "mobile",
games: [
{
name: "Temple Run",
id: 2259,
},
{
name: "Subway Surfer",
id: 2271,
},
{
name: "Pubg",
id: 2272,
},
],
},
{
type: "pc",
games: [
{
name: "Pubg",
id: 222,
},
{
name: "Fortnite",
id: 2274,
},
{
name: "Nfs",
id: 2272,
},
],
},
];
obj2 = [
{
type: "mobile",
games: [
{
name: "Temple Runs",
id: 2259,
},
{
name: "Subway Surfer",
id: 2271,
},
{
name: "Pubg",
id: 2272,
},
],
},
{
type: "pc",
games: [
{
name: "Pubgs",
id: 222,
},
{
name: "Fortnite",
id: 2274,
},
{
name: "Nfs",
id: 2272,
},
],
},
];
How to achieve something like this ?
In order to find the difference, you will need to:
Map all of the updated platforms (type and games)
Filter the updated games and locate the original game by ID
Flat-map the games in each platform and include the type
const main = () => {
const delta = diff(changed, data);
console.log(delta);
};
const diff = (updated, original) =>
updated
.map(({ type, games }) => ({
type,
games: games
.filter(({ name, id }) => original
.find(platform => platform.type === type).games
.find(game => game.id === id)?.name !== name)
}))
.flatMap(({ type, games }) =>
games.map(({ name, id }) =>
({ name, id, type })));
const data = [{
type: "mobile",
games: [
{ name: "Temple Run", id: 2259 },
{ name: "Subway Surfer", id: 2271 },
{ name: "Pubg", id: 2272 }
],
}, {
type: "pc",
games: [
{ name: "Pubg", id: 222 },
{ name: "Fortnite", id: 2274 },
{ name: "Nfs", id: 2272 }
]
}];
const changed = [{
type: "mobile",
games: [
{ name: "Temple Runs", id: 2259 },
{ name: "Subway Surfer", id: 2271 },
{ name: "Pubg", id: 2272 }
],
}, {
type: "pc",
games: [
{ name: "Pubgs", id: 222 },
{ name: "Fortnite", id: 2274 },
{ name: "Nfs", id: 2272 }
]
}];
main();
.as-console-wrapper { top: 0; max-height: 100% !important; }

I want to return the groups and the names of the subjects in which they are enrolled

const groups = [
{
name: "1",
subjects: [1, 2]
},
{
name: "2",
subjects: [1]
},
]
const subjects = [
{
id: 1,
name: "English",
},
{
id: 2,
name: "Mathematics",
},
{
id: 3,
name: "Physics",
},
]
example:[
{
name: "1",
subjects: [
{
id: 1,
name: "English",
},
{
id: 2,
name: "Mathematics",
},
]
const groupsSubject = groups.map(group => {
return {
...group,
subjects: subjects.id
}
})
This is my answer:
const groups = [
{
name: '1',
subjects: [ 1, 2 ]
},
{
name: '2',
subjects: [ 1 ]
}
]
const subjects = [
{
id: 1,
name: 'English'
},
{
id: 2,
name: 'Mathematics'
},
{
id: 3,
name: 'Physics'
}
]
const group = (groups, subjects) => {
return groups.map((group) => ({
name: group.name,
subjects: subjects.filter((subject) => group.subjects.includes(subject.id))
}))
}
console.log(group(groups, subjects))
Output:
[
{ name: '1', subjects: [ [Object], [Object] ] },
{ name: '2', subjects: [ [Object] ] }
]
You can create an object lookup of subjects based on the id. Then iterate through your group and assign the respective subjects.
const groups = [ { name: "1", subjects: [1, 2] }, { name: "2", subjects: [1] }],
subjects = [ { id: 1, name: "English", }, { id: 2, name: "Mathematics", }, { id: 3, name: "Physics", }, ],
lookup = Object.fromEntries(subjects.map(o => [o.id, o])),
result = groups.map(({name, subjects}) => ({name, subjects: subjects.map(id => ({...lookup[id]}))}));
console.log(result);
.as-console-wrapper { min-height: 100%!important; top: 0; }
Using Map and Array#map, create a map where the subject id is the key and the subject is the value
Using Array#map, iterate over the groups array. In each iteration, the subjects list will be created using Array#map and Map#get to transform ids to objects
const _getGroupWithSubjectDetails = (groups = [], subjects = []) => {
const subjectMap = new Map(
subjects.map(subject => ([subject.id, subject]))
);
return groups.map(({ subjects = [], ...group }) => ({
...group,
subjects: subjects.map(subjectId => ({ ...(subjectMap.get(subjectId) || {}) }))
}));
}
const
groups = [ { name: "1", subjects: [1, 2] }, { name: "2", subjects: [1] } ],
subjects = [ { id: 1, name: "English" }, { id: 2, name: "Mathematics" }, { id: 3, name: "Physics" } ];
console.log( _getGroupWithSubjectDetails(groups, subjects) );

How to change value for object property in array if property not match with compared value?

I want to return array with properties which not matched by valuesToCompare array values
const arr = [
{value: "test1", name: "name1"},
{value: "test2", name: "name1"},
{value: "test3", name: "name1"},
{value: "test3", name: "name2"},
{value: "test4", name: "name2"},
]
const valuesToCompare = ["test1", "test2", "test3", "test4"]
expected output
[
{value: "test4", name: "name1"},
{value: "test1", name: "name2"},
{value: "test2", name: "name2"},
]
I'm not sure whether you want to match or exclude based on an array of values, so providing both:
const arr = [{
value: "test1",
name: "name1"
},
{
value: "test2",
name: "name1"
},
{
value: "test3",
name: "name1"
},
{
value: "test3",
name: "name2"
},
{
value: "test4",
name: "name2"
},
]
const valuesToCompare = ["test1", "test2"]
const excluding = arr.filter(obj => !valuesToCompare.includes(obj.value))
console.log("Excluding values:")
console.log(excluding)
const matching = arr.filter(obj => valuesToCompare.includes(obj.value))
console.log("Matching values:")
console.log(matching)
You could do like below:
group the arr by name
with each grouped, filter the value
flatten each group back into objects
const arr = [
{ value: "test1", name: "name1" },
{ value: "test2", name: "name1" },
{ value: "test3", name: "name1" },
{ value: "test3", name: "name2" },
{ value: "test4", name: "name2" },
];
const valuesToCompare = ["test1", "test2", "test3", "test4"];
const groupByName = arr.reduce((acc, el) => {
if (acc[el.name]) {
acc[el.name].push(el.value);
} else {
acc[el.name] = [el.value];
}
return acc;
}, {});
const res = Object.entries(groupByName)
.map(([k, v]) => [k, valuesToCompare.filter((vtc) => !v.includes(vtc))])
.map(([k, v]) => v.map((v) => ({ name: k, value: v })))
.flat();
console.log(res);
.as-console-wrapper { max-height: 100% !important; }

How to group by id array [duplicate]

This question already has answers here:
Most efficient method to groupby on an array of objects
(58 answers)
Closed 3 years ago.
Hello guys can you help me reduce arrays please. I have two arrays and I need group one of them by mid. Here you can find example
I have array of objects
const arr = [{
mid: 888,
name: "test"
},
{
mid: 888,
name: "test1"
},
{
mid: 888,
name: "test2"
},
{
mid: 777,
name: "test10"
},
]
But I need group by mid and get something like this
const arr = [{
mid: 888,
projects: [{
name: "test"
},
{
name: "test1"
},
{
name: "test2"
},
]
},
{
mid: 777,
projects: [{
name: "test10"
}, ]
}
]
const arr = [{
mid: 888,
name: "test"
},
{
mid: 888,
name: "test1"
},
{
mid: 888,
name: "test2"
},
{
mid: 777,
name: "test10"
}
];
let newArray = []
arr.map(item => item.mid).filter((value, index, self)=> {
return self.indexOf(value) === index;
}).forEach((mid)=>{
newArray.push({
mid,
projects: arr.filter(item => item.mid == mid).map(item =>{ return {name: item.name}; })
})
})
console.log(newArray)
other way with reduce:
const arr = [{
mid: 888,
name: "test"
},
{
mid: 888,
name: "test1"
},
{
mid: 888,
name: "test2"
},
{
mid: 777,
name: "test10"
}
];
newArray = arr.map(item => item.mid).filter((value, index, self)=> {
return self.indexOf(value) === index;
}).map(item=> { return {mid: item, projects: []}})
newArray = arr.reduce((res, current)=>{
let index = newArray.map(item => item.mid).indexOf(current.mid);
res[index].projects.push({name: current.name})
return res;
}, newArray)
console.log(newArray)
This would be not the fastest way, but may help to better understand the reduce function, by experimenting with snippet) * JsFiddle
let arr = [{
mid: 888,
name: 'test'
},
{
mid: 888,
name: 'test1'
},
{
mid: 888,
name: 'test2'
},
{
mid: 777,
name: 'test10'
},
]
let reduced = arr.reduce((prev, now) => {
// first iteration, prev == []
// now == { mid: 888, name: 'test' }
let index = prev.map(e => e.mid).indexOf(now.mid);
if (~index) { // if index found
prev[index].projects.push({
name: now.name
})
} else {
prev.push({
mid: now.mid,
projects: [{
name: now.name
}]
})
}
return prev;
}, []); /* Starting from empty array */
console.log( reduced );
You can group it like this.
var groupedData = _.mapValues(_.groupBy(arr, 'mid'),
clist => clist.map(car => _.omit(car, 'mid')));
and result will be
{888: [{
name: test
},
{
name: test1
},
{
name: test2
},
],
777: [{
name: test10
} ]}
Here is how just a reduce function can do the trick using filter and ternary case:
const arr = [{mid: 888,name: "test"},
{mid: 888,name: "test1"},
{mid: 888, name: "test2"},
{mid: 777, name: "test10"}];
let newArray = arr.reduce(function (r, row) {
let dt = r.filter(x => x.mid == row.mid);
dt.length ? dt[0].projects.push(row.name): r.push({mid: row.mid, projects: [row.name]});
return r;
}, []);
console.log(newArray);

Categories