How can i remove object from nested array? - javascript

I have this kind of json.
let arr1 = [
{
"packageReference": "1234",
"displayName": "Business",
"description": "Includes...",
"promotion": {
"packageReference": "1234",
"displayName": "$100 Standard",
"optionGroup": [
{
"displayName": "Access",
},
{
"displayName": "Contract"
},
{
"displayName": "Equipment"
},
{
"displayName": "Features"
},
{
"displayName": "Fees",
}
]
}
}
]
I need to remove only the object in the arr1[0].promotion.optionGroup where the displayName is 'Fees' and to return the new object without him.

You could do it by filtering the sub array like so:
let arr1 = [
{
"packageReference": "1234",
"displayName": "Business",
"description": "Includes...",
"promotion": {
"packageReference": "1234",
"displayName": "$100 Standard",
"optionGroup": [
{
"displayName": "Access",
},
{
"displayName": "Contract"
},
{
"displayName": "Equipment"
},
{
"displayName": "Features"
},
{
"displayName": "Fees",
}
]
}
}
];
arr1 = arr1.map(e => {
e['promotion']['optionGroup'] =
e['promotion']['optionGroup'].filter(s => s['displayName'] != 'Fees');
return e;
});
console.log(arr1);

// Get new array without the Fees one
const newGroup = arr1[0].promotion.optionGroup.filter(group => group.displayName !== 'Fees');
// Put new group into the object
arr1[0].promotion.optionGroup = newGroup;
Could also do it without creating a variable, but added it for cleanness.

Related

Generate dynamic payload as per nested array item click javascript

I have this JSON data:
{
"data": [
{
"category": {
"documentId": "c8kr0cv012vtr8vm3iug",
"title": "Art"
},
"subcategories": [
{
"documentId": "c8kr7nv012vtr8vm3l8g",
"title": "Architecture"
},
{
"documentId": "c8kr7nv012vtr8vm3lag",
"title": "Dance"
},
{
"documentId": "c8kr7nv012vtr8vm3lbg",
"title": "Fashion"
}
]
},
{
"category": {
"documentId": "c8kr0cv012vtr8vm3iqg",
"title": "Business"
},
"subcategories": [
{
"documentId": "c8kr3d7012vtr8vm3jjg",
"title": "Crypto"
},
{
"documentId": "c8kr3d7012vtr8vm3jj0",
"title": "Finance"
},
{
"documentId": "c8kr3d7012vtr8vm3jkg",
"title": "Marketing"
}
]
}
]
}
I have tagview in my mobile screen so user can select multiple subcategory at a same time by select deselect so if i choose 2 subcategory from Art and 2 from Business then expected post payload should be like below
{
"data": [
{
"category": "c8kr0cv012vtr8vm3iug",
"subcategories": [
"c8kr7nv012vtr8vm3l8g",
"c8kr7nv012vtr8vm3lag"
]
},
{
"category": "c8kr0cv012vtr8vm3iqg",
"subcategories": [
"c8kr3d7012vtr8vm3jjg",
"c8kr3d7012vtr8vm3jj0"
]
}
]
}
So my code is like below
const tempDefaultPayload = dataPayload.map(x => {
if (x.category) {
x.subcategories?.push(subcategory);
if (userData?.userInterests?.map(v => v.category.documentId === category)) {
const arrayNewData: any = [];
const newData: any = userData?.userInterests?.map(i =>
i.subcategories?.map(k => {
arrayNewData.push(k?.documentId);
return k?.documentId;
}),
);
x.subcategories?.push(...arrayNewData);
}
return x;
}
return x;
})
When I run above code payload is not passing correct
[
{
"category": "c8kr0cv012vtr8vm3iug",
"subcategories": [
"c8kr7nv012vtr8vm3l8g",
"c8kr7nv012vtr8vm3lag",
"c8kr3d7012vtr8vm3jjg",
"c8kr3d7012vtr8vm3jj0"
]
},
{
"category": "c8kr0cv012vtr8vm3iqg",
"subcategories": [
"c8kr7nv012vtr8vm3l8g",
"c8kr7nv012vtr8vm3lag",
"c8kr3d7012vtr8vm3jjg",
"c8kr3d7012vtr8vm3jj0"
]
}
]
It is passing all selected subcategory in both array any idea how can I solve this ?
If you have the selected tag ids in the array selectedTags and your json as a variable called data:
const tempDefaultPayload = {
data: data.data.map(x => {
"category": x.category.documentId,
"subcategories": x.subcategories.map(subcat =>
subcat.documentId).filter(item => selectedTags.includes(item))
})
}
Playground example

cognito user attributes to plain object

I'm trying to convert the Cognito user attributes I get from CognitoIdentityServiceProvider listUsersInGroup to plain object but I didn't found any library or AWS function that does it... then I tried to implement it by myself
That's what I came up with:
{
...user,
Attributes: user.Attributes.map((x) => ({ [x.Name]: x.Value })),
}
But that makes an array with objects and I'm trying to create an object with all the attributes...
[
{
"sub": "dasfdasfd-vcfdgfd",
},
{
"website": "aba",
},
{
"address": "new",
},
]
here is an example of the user's data (the attributes can be different from user to user):
user a:
[
{
"Name": "sub",
"Value": "dasfdasfd-vcfdgfd",
},
{
"Name": "website",
"Value": "aba",
},
{
"Name": "address",
"Value": "new",
},
{
"Name": "email_verified",
"Value": "false",
},
{
"Name": "phone_number_verified",
"Value": "false",
}
]
user b:
[
{
"Name": "custom:age",
"Value": "0",
},
{
"Name": "custom:height",
"Value": "0",
},
{
"Name": "email",
"Value": "dsafdsa#gmail.com",
}
]
You can use reduce
{
...user,
Attributes: user.Attributes.reduce((acc, { Name, Value }) => ({...acc, [Name]: Value }), {}),
}
Seems pretty simple just use loop. FYI : Array's map function always returns the array
function getAttributes(data){
let attributes = {};
for(let x of data){
attributes[x["name"]] = x["value"];
}
return attributes;
}
{
...user,
Attributes: getAttributes(user.Attributes)
}

Lodash to filter out an array of objects

I am trying to filter out a nested array of objects using lodash which is pretty straightforward but I am looking to avoid multiple calls.
I am looking to create 2 array of objects using a single lodash call/function. Looking to find object property "$isMultiAccount" if it exists put the whole object into one result set and if not put it to another ruleset.
Currently I am doing this with Lodash "has and filter" for first and for other "!has" which means same object is looped twice , as object is relatively large its creating bottleneck for speed
https://repl.it/repls/HomelyExpensiveTruetype
const item = {
"domains": [
{
"id": "dm11022",
"information":{
"description": "Customer",
"owner": {
"primary":{
"name": "James",
"phone": "NA"
},
"others": [
{
"$isMultiAccount": "./Yes"
}
]
}
}
},
{
"id": "dm12022",
"information":{
"description": "Customer",
"owner": {
"primary":{
"name": "James",
"phone": "NA"
},
"others": [
{
"$isMultiAccount": "./No"
}
]
}
}
},
{
"id": "dm12022",
"information":{
"description": "Customer",
"owner": {
"primary":{
"name": "James",
"phone": "NA"
},
"others": [
{
"conf": {
"isVpnBased":{
"accountType": "Primary"
}
}
}
]
}
}
}
]
}
/*
Expected result
output1 = [
{
"id": "dm11022",
"information":{
"description": "Customer",
"owner": {
"primary":{
"name": "James",
"phone": "NA"
},
"others": [
{
"$isMultiAccount": "./Yes"
}
]
}
}
},
{
"id": "dm12022",
"information":{
"description": "Customer",
"owner": {
"primary":{
"name": "James",
"phone": "NA"
},
"others": [
{
"$isMultiAccount": "./No"
}
]
}
}
}
]
// $isMultiAccount account do not exist in this object
output2 = [
{
"id": "dm12022",
"information":{
"description": "Customer",
"owner": {
"primary":{
"name": "James",
"phone": "NA"
},
"others": [
{
"conf": {
"isVpnBased":{
"accountType": "Primary"
}
}
}
]
}
}
}
]
*/
const item = {
"domains": [
{
"id": "dm11022",
"information":{
"description": "Customer",
"owner": {
"primary":{
"name": "James",
"phone": "NA"
},
"others": [
{
"$isMultiAccount": "./Yes"
}
]
}
}
},
{
"id": "dm12022",
"information":{
"description": "Customer",
"owner": {
"primary":{
"name": "James",
"phone": "NA"
},
"others": [
{
"$isMultiAccount": "./No"
}
]
}
}
},
{
"id": "dm12022",
"information":{
"description": "Customer",
"owner": {
"primary":{
"name": "James",
"phone": "NA"
},
"others": [
{
"conf": {
"isVpnBased":{
"accountType": "Primary"
}
}
}
]
}
}
}
]
}
const [areMulti, areNotMulti] = _.reduce(item.domains, (current, next) => {
return _.has(next, ‘information.owner.others.$isMultiAccount’)
? [current[0].concat(next), current[1]]
: [current[0], current[1].concat(next)];
}, [[], []]);
console.log(areMulti);
console.log(areNotMulti);
Since item.domains.information.owner.others is an array, you need to tackle it as follows:
let multi = [];
let notMulti = [];
_.each(item.domains, function (obj) {
if (obj.information.owner.others.length && _.has(obj.information.owner.others[0], '$isMultiAccount'))
multi.push(obj);
else
notMulti.push(obj);
});
console.log(multi);
console.log(notMulti);
Unfortunately, you have to iterate over the domains array as well ass on the owner.others array to determine if the object with specific key sits inside.
So the algorithm has O(n*m) complexity.
If you ask for a lodash function seems that the partition method is what you're looking for
As docs says:
Creates an array of elements split into two groups, the first of which contains elements predicate returns truthy for, the second of which contains elements predicate returns falsey for. The predicate is invoked with one argument: (value).
So it will be like:
_.partition(
item.domains,
e => _.some(
_.get(e, 'information.owner.others'),
el => _.has(el,"$isMultiAccount")
)
);
Watch out - some hack available!
However, if the you're 100% sure that the element you're looking for will be always at specific index (for example it is supposed to be always as first element - so index 0) you can limit the algorithm to have linear complexity O(n) as only the size of the domains array will matter in terms of performance.
The hackish solution assuming fixed array index=0:
_.partition(
item.domains,
e => _.has(e, 'information.owner.others.0.$isMultiAccount')
);
NOTE
Using lodash makes code a bit easier to read but of course it creates some performance overhead anyway.

push elements of each object inside each object inside another array

I have two arrays, one is my original one called data which consists of :
const datas = [
{
name: 'core Test',
item: [
{
name: 'test/core/core.js',
item: "item1"
}
]
},
{
name: 'users Test',
item: [
{
name: 'test/users/user.js',
item: "item2"
}
]
}
]
And i have another array called replace, which i'm trying to push each of its elements inside my original one, inside the
const replace = [
{
type: "test1",
number: "1",
},
{
type: "test2",
number: "2",
}
]
Here is my code :
const transformedData = datas.map(data => {
data.item = data.item.map(x => ({
name: x.name,
type: replace.map(y=>{return y;})
}))
return data
})
The output i get :
[
{
"name": "core Test",
"item": [
{
"name": "test/core/core.js",
"type": [
{ "type": "test1", "number": "1" },
{ "type": "test2", "number": "2" }
]
}
]
},
{
"name": "users Test",
"item": [
{
"name": "test/users/user.js",
"type": [
{ "type": "test1", "number": "1" },
{ "type": "test2", "number": "2" }
]
}
]
}
]
The output i want :
[
{
"name": "core Test",
"item": [
{
"name": "test/core/core.js",
"type": { "type": "test1", "number": "1" }
}
]
},
{
"name": "users Test",
"item": [
{
"name": "test/users/user.js",
"type": { "type": "test2", "number": "2" }
}
]
}
]
This is because you're mapping all the way through the replace array every single time for each time you're inside of a value inside of datas. Instead you want to keep track of the index with your original map so then you only have one instance each time.
Try something like:
const transformedData = datas.map((data, index) => {
data.item = data.item.map(x => ({
name: x.name,
type: replace[index]
}))
return data;
});

Building new JSON from existing one

I want to build an new JSON from existing one. The source has sections and rubrics that I no longer need for a listing. The new object called 'items' should have an array of the items.
The final JSON should be sorted by attribute 'name' and look like
{
"items": [
{
"id": 10000006,
"name": "Boah"
},
{
"id": 10000013,
"name": "Gut"
},
{
"id": 10000003,
"name": "Ipsum"
},
{
"id": 10000001,
"name": "Lorem"
},
{
"id": 10000005,
"name": "Lorum"
},
{
"id": 10000004,
"name": "Name"
},
{
"id": 10000002,
"name": "Stet"
}
]
}
For building the new JSON I get this source:
{
"sections": [
{
"name": "FooBar",
"rubrics": [
{
"name": "Foo",
"items": [
{
"id": 10000001,
"name": "Lorem"
},
{
"id": 10000002,
"name": "Stet"
},
{
"id": 10000003,
"name": "Ipsum"
}
]
},
{
"name": "Bar",
"items": [
{
"id": 10000004,
"name": "Name"
},
{
"id": 10000005,
"name": "Lorum"
},
{
"id": 10000006,
"name": "Boah"
}
]
}
]
},
{
"name": "BlahBloob",
"rubrics": [
{
"name": "Bla",
"items": [
{
"id": 10000013,
"name": "Gut"
}
]
},
{
"name": "Bloob",
"items": [
{
"id": 10000014,
"name": "Name"
},
{
"id": 10000015,
"name": "Lorem"
}
]
}
]
}
]
}
What do you think? How can I do this with plain JavaScript or maybe TypeScript?
Thanks for reading and have time for my question. And thanks for reply in advance.
Here you go. You just need to iterate over each rubric of each section of your source to get the items. At the end, sort your list of items by items, and you're done.
This example uses ES6 syntax, but it's easy to convert it to ES5 if needed.
function extractItems(source) {
const items = [];
for (const section of source.sections) {
for (const rubric of section.rubrics) {
items.push(...rubric.items);
}
}
items.sort((a, b) => a.name.localeCompare(b.name));
return { items };
}
A more functional approach use map and reduce to pick the rubrics and merge them.
data.sections
.map(section => section.rubrics) // get rubrics
.reduce((a, b) => a.concat(b)) // merge rubrics
.map(rubric => rubric.items) // get items from each rubric
.reduce((a, b) => a.concat(b)) // merge items
.sort((a, b) => a.name.localeCompare(b.name)); // sort
function(oldObj) {
var newObj = {
"items": []
};
oldObj.sections.forEach(function(section) {
section.rubrics.forEach(function(rubric) {
rubric.items.forEach(function(item) {
newObj.items.push(item);
});
});
});
newObj.items = newObj.items.sort(function(a, b) {
if (a.name < b.name) { return -1; }
if (a.name > b.name) { return 1; }
return 0;
});
return newObj;
}
And simply use JSON.parse() and JSON.stringify() to convert JSON to and from objects.
It might help you
var data ={
"sections": [
{
"name": "FooBar",
"rubrics": [{"name": "Foo", "items": [{"id": 10000001,"name": "Lorem"}, {"id": 10000002,"name": "Stet"}, {"id": 10000003,"name": "Ipsum"}]
}, {
"name": "Bar",
"items": [{
"id": 10000004,
"name": "Name"
}, {
"id": 10000005,
"name": "Lorum"
}, {
"id": 10000006,
"name": "Boah"
}]
}]
}, {
"name": "BlahBloob",
"rubrics": [{
"name": "Bla",
"items": [{
"id": 10000013,
"name": "Gut"
}]
}, {
"name": "Bloob",
"items": [{
"id": 10000014,
"name": "Name"
}, {
"id": 10000015,
"name": "Lorem"
}]
}]
}]
};
var itemObj = {};
var itemArr = [];
var sections = data.sections;
for(var i=0;i<sections.length;i++)
{
for(var j=0;j<sections[i].rubrics.length;j++){
for(var k=0;k<sections[i].rubrics[j].items.length;k++){
var itemObj;
itemObj['id'] = sections[i].rubrics[j].items[k].id;
itemObj['name'] = sections[i].rubrics[j].items[k].name;
itemArr.push(itemObj);
}
}
}
var finalObj = {"items":itemArr};
console.log(finalObj);
JSFiddle

Categories

Resources