Get the aggregate size of nested object - javascript

I have the following JS object:
[
{
title: "cat1",
children: [
{
title: "Monday",
children: [
{ title: "size1", size: 120 },
{ title: "size2", size: 75 },
{ title: "size3", size: 45 }
]
},
{
title: "Tuesday",
children: [
{ title: "size1", size: 105 },
{ title: "size2", size: 45 },
{ title: "size3", size: 75 }
]
}
]
},
{
title: "cat2",
children: [
{
title: "Monday",
children: [
{ title: "size1", size: 60 },
{ title: "size2", size: 40 }
]
}
]
}
];
and want to evaluate the aggregate of the size in each nest. Say I will get
[
{
title: "cat1",
size: 465,
children: [
{
title: "Monday",
size: 240
},
{
title: "Tuesday",
size: 225
}
]
},
{
title: "cat2",
size: 200,
children: [
{
title: "Monday",
size: 200
}
]
}
];
So far I have the following code, but it doesn't work if the nest is two or more. I guess it's because of something related to "call by reference" but not sure how to fix it. Could anyone give me a help?
const getFrequency = (item: any) => {
console.log(item);
if (item[0].children[0].children === undefined) {
item.map((item2: any) => ({
title: item2.title,
size: item2.children.reduce((prev: number, curr: any) => prev + curr.size, 0)
}));
} else {
item.map((item2: any) => ({
title: item2.title,
children: item2.children,
size: getFrequency(item2.children)
}));
}
return item;
};
const freqData = getFrequency(nestedData);
EDIT: It has to be capable of recursively processing data with more than two nests.

const arr = [{
title: "cat1",
size: 465,
children: [{
title: "Monday",
size: 240
},
{
title: "Tuesday",
size: 225
}
]
},
{
title: "cat2",
size: 200,
children: [{
title: "Monday",
size: 200
}]
}
];
arr.map(el => {
const childSize = el.children.reduce((acc, item) => acc += item.size, 0);
return { ...el,
size: childSize
}
});
console.log(arr)

Related

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; }

How to insert entries from into a nested JavaScript Object

I'm facing trouble in making a nested insertion of a particular entry into my data structure. The 'positionValue' in the 'data' object below has to be inserted into 'mystructure' based on whether it is Team1 or Team2, and based on the category 'Lombard Loans/Time Deposits/Demand Deposits' and then further based on 'name' of the product (the last nested structure).
The original object:
data: [
{
balanceSheetPositionResults: [
{
positionValue: 12,
balanceSheetPosition: {
name: "asset_bc_lombard_a_onsight",
category: "LOMBARD_LOANS",
type: "ASSET"
},
},
{
positionValue: 58,
balanceSheetPosition: {
name: "liability_bc_timedeposits",
category: "TIME_DEPOSITS",
type: "ASSET"
},
},
{
positionValue: 58,
balanceSheetPosition: {
name: "liability_bc_demanddeposits",
category: "DEMAND_DEPOSITS",
type: "ASSET"
},
},
{
positionValue: 10,
balanceSheetPosition: {
name: "asset_bc_lombard_a_lt1m",
category: "LOMBARD_LOANS",
type: "ASSET"
},
}
],
bank: {
name: "Team1"
},
game: {
name: "TestGame"
},
bsSum: 2,
period: {
index: 1
},
},
{
balanceSheetPositionResults: [
{
positionValue: 12,
balanceSheetPosition: {
name: "asset_bc_lombard_a_onsight",
category: "LOMBARD_LOANS",
type: "ASSET"
},
},
{
positionValue: 58,
balanceSheetPosition: {
name: "liability_bc_timedeposits",
category: "TIME_DEPOSITS",
type: "ASSET"
},
},
{
positionValue: 58,
balanceSheetPosition: {
name: "liability_bc_demanddeposits",
category: "DEMAND_DEPOSITS",
type: "ASSET"
},
},
{
positionValue: 10,
balanceSheetPosition: {
name: "asset_bc_lombard_a_lt1m",
category: "LOMBARD_LOANS",
type: "ASSET"
},
}
],
bank: {
name: "Team2"
},
game: {
name: "TestGame"
},
bsSum: 2,
period: {
index: 1
}
}
]
The structure that I made after some transformation (this is just a snippet):
{ mystructure:
[
{ name: 'Team2',
LOMBARD_LOANS:
[ { name: 'asset_bc_lombard_a_onsight'
},
{ name: 'asset_bc_lombard_a_lt1m'
}
],
DEMAND_DEPOSITS:
[ { name: 'liability_bc_demanddeposits'
}
],
TIME_DEPOSITS:
[ { name: 'liability_bc_timedeposits'
}
]
},
{ name: 'Team1',
LOMBARD_LOANS:
[ { name: 'asset_bc_lombard_a_onsight'
},
{ name: 'asset_bc_lombard_a_lt1m'
}
],
DEMAND_DEPOSITS:
[ { name: 'liability_bc_demanddeposits'
}
],
TIME_DEPOSITS:
[ { name: 'liability_bc_timedeposits'
}
]
}
]
}
The result that would look like:
{ mystructure:
[
{ name: 'Team2',
LOMBARD_LOANS:
[ { name: 'asset_bc_lombard_a_onsight',
positionValue: 12
},
{ name: 'asset_bc_lombard_a_lt1m',
positionValue: 58
}
],
DEMAND_DEPOSITS:
[ { name: 'liability_bc_demanddeposits',
positionValue: 58
}
],
TIME_DEPOSITS:
[ { name: 'liability_bc_timedeposits',
positionValue: 10
}
]
},
{ name: 'Team1',
LOMBARD_LOANS:
[ { name: 'asset_bc_lombard_a_onsight',
positionValue: 12
},
{ name: 'asset_bc_lombard_a_lt1m',
positionValue: 58
}
],
DEMAND_DEPOSITS:
[ { name: 'liability_bc_demanddeposits',
positionValue: 58
}
],
TIME_DEPOSITS:
[ { name: 'liability_bc_timedeposits',
positionValue: 10
}
]
}
]
}
Assuming each bank name comes only once, pass your original array to this transformer :
function transformData(data) {
return data.map(entry => {
const loanType = {};
entry.balanceSheetPositionResults.forEach(balanceEntry => {
const { name, category, type } = balanceEntry.balanceSheetPosition;
if (!(category in loanType)) {
loanType[category] = [];
}
loanType[category].push({
name,
positionValue: balanceEntry.positionValue
});
});
return {
name: entry.bank.name,
...loanType
};
});
}

How to nest multiple groupby with loadash/javascript

Thank you in advance to whoever can help me. I am trying to display data using SectionList in React Native. I have written my code below displaying what I am trying to accomplish. A regular javascript solution will work. I want the data to first be grouped together by date, and inside of that date, I need them grouped by location.
It's important that it has a title and data key
I have data in this format:
[ { game_id: 1171,
date: '2018-11-17',
location: 'Plaza'
},
{ game_id: 1189,
date: '2018-11-17',
location: 'Field - Kickball'
},
{ game_id: 1489,
date: '2018-11-16',
location: 'Field - Kickball'
},
{ game_id: 1488,
date: '2018-11-16',
location: 'Field - Soccer'
}
]
I need the output to show:
data = [{
title: "2018-11-17",
data: [{
title: "Field - Kickball",
data: [{
game_id: 1189,
date: '2018-11-17',
location: 'Field - Kickball'
}]
},
{
title: "Plaza",
data: [{
game_id: 1171,
date: '2018-11-17',
location: 'Plaza'
}]
}
]
},
{
title: "2018-11-16",
data: [{
title: "Field - Kickball",
data: [{
game_id: 1489,
date: '2018-11-16',
location: 'Field - Kickball'
}]
},
{
title: "Field - Soccer",
data: [{
game_id: 1488,
date: '2018-11-16',
location: 'Field - Soccer'
}]
}
]
}
]
I have already tried this
const games = [data here]
var groups = _(games)
.groupBy(x => x.date)
.map(value => {
return _.groupBy(value, 'location')
.map(({key, value}) => ({title: key, data: value}))
})
.map((value, key) => {
return ({title: value[Object.keys(value)[0]][0].date, data: value})
})
Use reduce like so:
const data = [{game_id:1171,date:'2016-11-17T05:00:00.000Z',time:'08:00:00',category:'Ch B Coed',background:'#FFFF00',textcolor:'#000000',bold:0,sport:'Newcomb',location:'Plaza',text:'COL2 vs. USA1 1171'},{game_id:1189,date:'2016-11-17T05:00:00.000Z',time:'08:50:00',category:'Ch A Coed',background:'#FF33CC',textcolor:'#000000',bold:0,sport:'Kickball',location:'Field - Kickball',text:'COL1 vs. USA1 1189'},{game_id:1489,date:'2016-2-17T05:00:00.000Z',time:'04:50:00',category:'Ch B Coed',background:'#FF33CC',textcolor:'#000000',bold:0,sport:'Kickball',location:'Field - Kickball',text:'COL2 vs. USA3 1489'}];
const res = Object.values(data.reduce((acc, { date, ...rest }) => acc[date] ? { ...acc, [date]: { ...acc[date], data: acc[date].data.concat({ date, ...rest })} } : { ...acc, [date]: { title: date, data: [{ date, ...rest }] }}, {}));
console.log(res);
.as-console-wrapper { max-height: 100% !important; top: auto; }
Pardon me if I am missing something but this to me it seems can be done in somewhat simpler manner via Array.reduce:
let data = [{ game_id: 1171, date: '2016-11-17T05:00:00.000Z', time: '08:00:00', category: 'Ch B Coed', background: '#FFFF00', textcolor: '#000000', bold: 0, sport: 'Newcomb', location: 'Plaza', text: 'COL2 vs. USA1 1171' }, { game_id: 1189, date: '2016-11-17T05:00:00.000Z', time: '08:50:00', category: 'Ch A Coed', background: '#FF33CC', textcolor: '#000000', bold: 0, sport: 'Kickball', location: 'Field - Kickball', text: 'COL1 vs. USA1 1189' }, { game_id: 1489, date: '2016-2-17T05:00:00.000Z', time: '04:50:00', category: 'Ch B Coed', background: '#FF33CC', textcolor: '#000000', bold: 0, sport: 'Kickball', location: 'Field - Kickball', text: 'COL2 vs. USA3 1489' } ]
let result = data.reduce((r, c) => {
r[c.date] = r[c.date] || {title: c.date, data: []}
r[c.date].data = [...(r[c.date].data || []), c]
return r
}, {})
console.log(Object.values(result))

how to filter nested array like this?

I am having response like below
let m = [
{
name: 'Summary',
subListExpanded: false,
subList: [
]
},
{
name: 'Upload',
subListExpanded: false,
subList: [
]
},
{
name: 'Tasks',
subListExpanded: false,
subList: [
]
},
{
name: 'Dashboard',
subListExpanded: false,
subList: [
]
},
{
name: 'Master',
subListExpanded: false,
subList: [
{
id: 'user-master',
name: 'User-Master'
},
{
id: 'menu-master',
name: 'Menu-Master'
},
{
id: 'entity-master',
name: 'Entity-Master'
},
{
id: 'vendor-master',
name: 'Vendor-Master'
},
{
id: 'xxx-master',
name: 'xxx-Master'
}
]
}
];
If i search m the filter should be like this
[
{
name: 'Summary',
subListExpanded: false,
subList: [
]
},
{
name: 'Master',
subListExpanded: false,
subList: [
{
id: 'user-master',
name: 'User-Master'
},
{
id: 'menu-master',
name: 'Menu-Master'
},
{
id: 'entity-master',
name: 'Entity-Master'
},
{
id: 'vendor-master',
name: 'Vendor-Master'
},
{
id: 'xxx-master',
name: 'xxx-Master'
}
]
}
];
if i search master the filter response should like this?
[
{
name: 'Master',
subListExpanded: false,
subList: [
{
id: 'user-master',
name: 'User-Master'
},
{
id: 'menu-master',
name: 'Menu-Master'
},
{
id: 'entity-master',
name: 'Entity-Master'
},
{
id: 'vendor-master',
name: 'Vendor-Master'
},
{
id: 'xxx-master',
name: 'xxx-Master'
}
]
}
];
if i search xxx-master the filter response should be
[
{
name: 'Master',
subListExpanded: false,
subList: [
{
id: 'xxx-master',
name: 'xxx-Master'
}
]
}
];
if i search slkvcsmcskc filter response like
[]
my typescript code is not working properly .please help me to fix this>
m.filter(x=> x.name.toLowerCase() === search.toLowerCase() || x.subList.some(x1=> x1.name.toLowerCase()===search.toLowerCase()))
The following code gives the desired output. Note that I added some complexity which may not be needed for your use case. However, the example should work for lists with arbitrary deep nesting (see 'bar' example).
let m = [
{
name: 'Summary',
subListExpanded: false,
subList: [
]
},
{
name: 'Upload',
subListExpanded: false,
subList: [
{
name: 'foo',
subList: [
{
name: 'bar',
}
],
}
]
},
{
name: 'Tasks',
subListExpanded: false,
subList: [
]
},
{
name: 'Dashboard',
subListExpanded: false,
subList: [
]
},
{
name: 'Master',
subListExpanded: false,
subList: [
{
id: 'user-master',
name: 'User-Master'
},
{
id: 'menu-master',
name: 'Menu-Master'
},
{
id: 'entity-master',
name: 'Entity-Master'
},
{
id: 'vendor-master',
name: 'Vendor-Master'
},
{
id: 'xxx-master',
name: 'xxx-Master'
}
]
}
];
function search (input, query) {
const queryReg = new RegExp(query, 'i');
function searchInternal (data) {
let result = [];
data.forEach(item => {
const parentMatch = queryReg.test(item.name);
let subMatch = false;
if (item.subList) {
let subResult = searchInternal(item.subList);
subMatch = subResult.length > 0;
item.subList = subMatch ? subResult : [];
}
// push parent if it matches for itself or a child (list) matches
if (parentMatch || subMatch) result.push(item);
});
return result;
}
return searchInternal(JSON.parse(JSON.stringify(input)) /* create a working copy with JSON.parse(...) */);
}
console.log('master', search(m, 'master'));
console.log('xxx-master', search(m, 'xxx-master'));
console.log('m', search(m, 'm'));
console.log('bar', search(m, 'bar'));
console.log('slkvcsmcskc', search(m, 'slkvcsmcskc'));
Actually it should go like this:
obj = {
_id: "sjkd9skj",
data: {
dektop: [
{
x: 2,
y: 3,
t: { key: 'aabbcc'}
},
...
],
mobile: [
{
x: 4,
y: 3,
t: { key: 'ffff'}
},
...
],
print: [
{
x: 7,
y: 5,
t: { key: 'ppp'}
},
...
]
}
}

lodash recursively find item in array

What might be the easiest solution in lodash to recursively find item in array by, for example, 'text' field with value 'Item-1-5-2'?
const data = [
{
id: 1,
text: 'Item-1',
children: [
{ id: 11, text: 'Item-1-1' },
{ id: 12, text: 'Item-1-2' },
{ id: 13, text: 'Item-1-3' },
{ id: 14, text: 'Item-1-4' },
{
id: 15,
text: 'Item-1-5',
children: [
{ id: 151, text: 'Item-1-5-1' },
{ id: 152, text: 'Item-1-5-2' },
{ id: 153, text: 'Item-1-5-3' },
]
},
]
},
{
id: 2,
text: 'Item-2',
children: [
{ id: 21, text: 'Item-2-1' },
{ id: 22, text: 'Item-2-2' },
{ id: 23, text: 'Item-2-3' },
{ id: 24, text: 'Item-2-4' },
{ id: 25, text: 'Item-2-5' },
]
},
{ id: 3, text: 'Item-3' },
{ id: 4, text: 'Item-4' },
{ id: 5, text: 'Item-5' },
];
Thank You!
In plain Javascript, you could use Array#some recursively.
function getObject(array, key, value) {
var o;
array.some(function iter(a) {
if (a[key] === value) {
o = a;
return true;
}
return Array.isArray(a.children) && a.children.some(iter);
});
return o;
}
var data = [{ id: 1, text: 'Item-1', children: [{ id: 11, text: 'Item-1-1' }, { id: 12, text: 'Item-1-2' }, { id: 13, text: 'Item-1-3' }, { id: 14, text: 'Item-1-4' }, { id: 15, text: 'Item-1-5', children: [{ id: 151, text: 'Item-1-5-1' }, { id: 152, text: 'Item-1-5-2' }, { id: 153, text: 'Item-1-5-3' }, ] }, ] }, { id: 2, text: 'Item-2', children: [{ id: 21, text: 'Item-2-1' }, { id: 22, text: 'Item-2-2' }, { id: 23, text: 'Item-2-3' }, { id: 24, text: 'Item-2-4' }, { id: 25, text: 'Item-2-5' }, ] }, { id: 3, text: 'Item-3' }, { id: 4, text: 'Item-4' }, { id: 5, text: 'Item-5' }, ];
console.log(getObject(data, 'text', 'Item-1-5-2'));
.as-console-wrapper { max-height: 100% !important; top: 0; }
It's the perfect spot for a recursive function.
function findText(items, text) {
if (!items) { return; }
for (const item of items) {
// Test current object
if (item.text === text) { return item; }
// Test children recursively
const child = findText(item.children, text);
if (child) { return child; }
}
}
That's also the best way to get the maximum performances. Traversal is some in depth-first-search way.

Categories