Create a level for each object in the flatenned tree - javascript

I want to implement a Angular material flat tree. I am new to reduce function and closure understanding the below method is also difficult for me. Can it be simplified I am using the below code to flatten a recursive tree. My tree look as below and I can rewrite the flattened code with level included. How do I incorporate level here. How can this be achieved, Please help.
[ {
"sectionIdent": "0/0",
"examSectionID": "59f87638-a4ce-4861-81f9-562a887ba3e5",
"sectionTitle": "Timed exam section 1",
"sectionOrder": null,
"randomCount": null,
"mixContent": null,
"totalCount": 0,
"titleError": false,
"randomError": false,
"items": null,
"delNavInfo": null,
"subExamSections": [{
"sectionIdent": "0/0/0",
"examSectionID": "59f87638-a4ce-4861-81f9-562a887ba3e5",
"sectionTitle": "Timed exam section 2",
"sectionOrder": null,
"randomCount": null,
"mixContent": null,
"totalCount": 0,
"titleError": false,
"randomError": false,
"items": null,
"delNavInfo": null,
"subExamSections": [],
"mainSection": true
},
{
"sectionIdent": "0/0/1",
"examSectionID": "59f87638-a4ce-4861-81f9-562a887ba3e5",
"sectionTitle": "Timed exam section 3",
"sectionOrder": null,
"randomCount": null,
"mixContent": null,
"totalCount": 0,
"titleError": false,
"randomError": false,
"items": null,
"delNavInfo": null,
"subExamSections": [{
"sectionIdent": "0/0/1/0",
"examSectionID": "59f87638-a4ce-4861-81f9-562a887ba3e5",
"sectionTitle": "Timed exam section 4",
"sectionOrder": null,
"randomCount": null,
"mixContent": null,
"totalCount": 0,
"titleError": false,
"randomError": false,
"items": null,
"delNavInfo": null,
"subExamSections": null,
"mainSection": true
}
],
"mainSection": true
}
],
"mainSection": true
}
];
I want it in the format like this
[{
...sectionTitle:"Timed exam section 1",
level:0
},
{
...sectionTitle:"Timed exam section 2",
level:1
},
{
...sectionTitle:"Timed exam section 3",
level:1
},
{
...sectionTitle:"Timed exam section 4",
level:2
},
]
Code:
buildFileTree(nodeArray: any, level: number): ExamSection[] {
return nodeArray.reduce(function recur(accumulator, curr) {
var keys = Object.keys(curr);
keys.splice(keys.indexOf('subExamSections'), 1);
accumulator.push(keys.reduce(function (entry, key) {
entry[key] = curr[key];
return entry;
}, {}));
if (curr.subExamSections && curr.subExamSections.length) {
return accumulator.concat(curr.subExamSections.reduce(recur, []));
}
return accumulator;
}, []);
}

You can get the structure you are looking for with this:
function buildFileTree(tree = [], level = 0) {
return Array.prototype.concat
.apply(
tree.map(item => ({ ...item, level })), // Add 'level' property
tree.map(item => {
const subtree = item.subExamSections || []
const nextLevel = level + 1
return buildFileTree(subtree, nextLevel) // Combine with sub-tree recursively
})
)
.map(({ sectionTitle, level }) => ({ sectionTitle, level })) // Extract the desired properties
}

Concetp used :
... Destructuring to add and remove properties,
Recussiong: for looping,
map to create new array,
foreach to iteration.
let loop = (sections = [], flatSection = []) => {
if(sections) {
let editedShallowCopy = sections.map((s, i) => {
let { subExamSections , ...rest } = s; // destructure to remove property
return { ...rest, level: flatSection.length + i + 1 } // adding the new property
});
flatSection.push(...editedShallowCopy); // adding it flatSection
sections?.forEach(section => loop(section.subExamSections, flatSection)); // go in deeper levels of tree, Recussiong loop
}
return flatSection;
}
console.log(loop(tree))
let tree = [{
"sectionIdent": "0/0",
"examSectionID": "59f87638-a4ce-4861-81f9-562a887ba3e5",
"sectionTitle": "Timed exam section 1",
"sectionOrder": null,
"randomCount": null,
"mixContent": null,
"totalCount": 0,
"titleError": false,
"randomError": false,
"items": null,
"delNavInfo": null,
"subExamSections": [{
"sectionIdent": "0/0/0",
"examSectionID": "59f87638-a4ce-4861-81f9-562a887ba3e5",
"sectionTitle": "Timed exam section 2",
"sectionOrder": null,
"randomCount": null,
"mixContent": null,
"totalCount": 0,
"titleError": false,
"randomError": false,
"items": null,
"delNavInfo": null,
"subExamSections": [],
"mainSection": true
},
{
"sectionIdent": "0/0/1",
"examSectionID": "59f87638-a4ce-4861-81f9-562a887ba3e5",
"sectionTitle": "Timed exam section 3",
"sectionOrder": null,
"randomCount": null,
"mixContent": null,
"totalCount": 0,
"titleError": false,
"randomError": false,
"items": null,
"delNavInfo": null,
"subExamSections": [{
"sectionIdent": "0/0/1/0",
"examSectionID": "59f87638-a4ce-4861-81f9-562a887ba3e5",
"sectionTitle": "Timed exam section 4",
"sectionOrder": null,
"randomCount": null,
"mixContent": null,
"totalCount": 0,
"titleError": false,
"randomError": false,
"items": null,
"delNavInfo": null,
"subExamSections": null,
"mainSection": true
}
],
"mainSection": true
}
],
"mainSection": true
}];
let loop = (sections = [], flatSection = []) => {
if (sections) {
let editedShallowCopy = sections.map((s, i) => {
let {
subExamSections,
...rest
} = s; // destructure to remove property
return { ...rest,
level: flatSection.length + i + 1
} // adding the new property
});
flatSection.push(...editedShallowCopy); // adding it flatSection
sections.forEach(section => loop(section.subExamSections, flatSection)); // go in deeper levels of tree
}
return flatSection;
}
console.log(loop(tree))

Related

Add new property to react state

I am trying to add a new property to the state "initialTags". However, I do not know how to do that. I have tried to loop through the object to set the new property, however it didnt work. Also, the setState it all in a same function, but since setState is async, I am unable to setState on the same state after my first setState statement.
Initializing the state:
this.setState({ initialTags: [...tempTarget] }, () => console.log("initTags == ", this.state.initialTags));
Array of Object after setState:
[
{
"name": "AQS",
"projectId": "MTYzMDE1MzU3NjA3My10ZXN0MTA",
"projectName": null,
"isUserForAllProject": false
},
{
"name": "ED",
"projectId": null,
"projectName": null,
"isUserForAllProject": null
},
{
"name": "PAID",
"projectId": null,
"projectName": null,
"isUserForAllProject": null
},
{
"name": "QS",
"projectId": null,
"projectName": null,
"isUserForAllProject": null
}
]
The New property that needs to be added in the Object:
[
{
"name": "AQS",
"projectId": "MTYzMDE1MzU3NjA3My10ZXN0MTA",
"projectName": null,
"isUserForAllProject": false,
"return": []
},
{
"name": "ED",
"projectId": null,
"projectName": null,
"isUserForAllProject": null,
"return": []
},
{
"name": "PAID",
"projectId": null,
"projectName": null,
"isUserForAllProject": null,
"return": []
},
{
"name": "QS",
"projectId": null,
"projectName": null,
"isUserForAllProject": null,
"return": []
}
]
EDIT: SOLUTION
this.setState({ initialTags: [...tempTarget.map(item => ({...item, returnVal: []}))] })
this.setState((prev) => {
return {
...prev,
initialValues: prev.initialValues.map((item) => {
return {
...item,
returnValue: []
};
})
};
});
You shoudn't use return as it is a keyword.

How to filter an array of objects based on specific objects

I am trying to 'filter' this array of objects to only get the newCases and date. Moreover, I would like to convert this into a DataSet with x being the date and y being newCases.
"actualsTimeseries": [
{
"cases": 1,
"deaths": 0,
"positiveTests": null,
"negativeTests": null,
"contactTracers": null,
"hospitalBeds": {
"capacity": null,
"currentUsageTotal": null,
"currentUsageCovid": null
},
"icuBeds": {
"capacity": null,
"currentUsageTotal": null,
"currentUsageCovid": null
},
"newCases": null,
"newDeaths": null,
"vaccinesAdministeredDemographics": null,
"vaccinationsInitiatedDemographics": null,
"date": "2020-03-09"
},
{
"cases": 3,
"deaths": 0,
"positiveTests": null,
"negativeTests": null,
"contactTracers": null,
"hospitalBeds": {
"capacity": null,
"currentUsageTotal": null,
"currentUsageCovid": null
},
"icuBeds": {
"capacity": null,
"currentUsageTotal": null,
"currentUsageCovid": null
},
"newCases": 2,
"newDeaths": 0,
"vaccinesAdministeredDemographics": null,
"vaccinationsInitiatedDemographics": null,
"date": "2020-03-10"
},
{
"cases": 3,
"deaths": 0,
"positiveTests": null,
"negativeTests": null,
"contactTracers": null,
"hospitalBeds": {
"capacity": null,
"currentUsageTotal": null,
"currentUsageCovid": null
},
"icuBeds": {
"capacity": null,
"currentUsageTotal": null,
"currentUsageCovid": null
},
"newCases": 0,
"newDeaths": 0,
"vaccinesAdministeredDemographics": null,
"vaccinationsInitiatedDemographics": null,
"date": "2020-03-11"
},
...
}
I have attempted to do this, but need help on how to sort the dates.
const dataArray = actualsTimeseries.map((info) => info);
const getPastCases = () =>
Object.entries(dataArray).sort(([date1], [date2]) =>
date1.localeCompare(date2)
);
const DataSet = (casesByDate) =>
casesByDate.map(([dateString, cases]) => ({
x: new Date(dateString),
y: cases.newCases,
}));
const resData = DataSet(getPastCases());

Remove object array duplicates and store non duplicate values in array

I need to merge an array of deliveries that have notes, how would I remove the duplicate object but still keep the note string and store it in an array for the non duplicated object
Key begin the delivery number:
"data": [
{
"deliveryNumber": "0000001",
"deliveryDate": "2021-10-01T00:00:00.000Z",
"dateBeginProcess": null,
"dateFinishedProcess": null,
"status": "",
"notes": "Note 1"
},
{
"deliveryNumber": "0000001",
"deliveryDate": "2021-10-01T00:00:00.000Z",
"dateBeginProcess": null,
"dateFinishedProcess": null,
"status": "Ready",
"notes": "Note 2"
},
{
"deliveryNumber": "0000002",
"deliveryDate": "2021-10-01T14:21:00.000Z",
"dateBeginProcess": null,
"dateFinishedProcess": null,
"status": "Ready",
"notes": null
}
]
into
"data": [
{
"deliveryNumber": "0000001",
"deliveryDate": "2021-10-01T00:00:00.000Z",
"dateBeginProcess": null,
"dateFinishedProcess": null,
"status": "Ready",
"notes": ["Note 1", "Note 2"]
},
{
"deliveryNumber": "0000002",
"deliveryDate": "2021-10-01T14:21:00.000Z",
"dateBeginProcess": null,
"dateFinishedProcess": null,
"status": "Ready",
"notes": null
}
]
You can use Array.prototype.forEach() to loop over the notes array. If a note is encountered twice add their notes together.
const notes = [
{
"deliveryNumber": "0000001",
"deliveryDate": "2021-10-01T00:00:00.000Z",
"dateBeginProcess": null,
"dateFinishedProcess": null,
"status": "",
"notes": "Note 1"
},
{
"deliveryNumber": "0000001",
"deliveryDate": "2021-10-01T00:00:00.000Z",
"dateBeginProcess": null,
"dateFinishedProcess": null,
"status": "Ready",
"notes": "Note 2"
},
{
"deliveryNumber": "0000002",
"deliveryDate": "2021-10-01T14:21:00.000Z",
"dateBeginProcess": null,
"dateFinishedProcess": null,
"status": "Ready",
"notes": null
}
]
let filteredArray = []
notes.forEach(note => {
let noteFound = filteredArray.find(el => el.deliveryNumber === note.deliveryNumber)
if(noteFound){
// not first encounter
// add notes together
noteFound.notes.push(note.notes)
}else{
// first encounter
// make notes an array
note.notes = [note.notes||'']
filteredArray.push(note)
}
})
console.log(filteredArray)

Compare 3 arrray and find combination in javascript

I have 3 arrays as below
A: [
{
"label": "100Watts",
"value": "100Watts",
},
{
"label": "135Watts",
"value": "135Watts",
} ]
B: [
{
"label": "Large|100cm",
"value": "Large|100cm"
},
{
"label": "Small|125mm",
"value": "Small|125mm"
}
]
C: [
{
"label": "Black",
"value": "Black",
},
{
"label": "Black",
"value": "Black",
}
]
I have one master array as below
result:[
{
"x_powerConsumption": "100Watts",
"x_size": "Small|125mm",
"x_color": "Black",
},
{
"x_powerConsumption": "135Watts",
"x_size": "Large|100cm",
"x_color": "Black",
}
]
My code as below
let newArray = A.filter(o1 => result.some(o2 => o1.label === o2.x_size));
let newArray2 = B.filter(o1 => result.some(o2 => o1.label === o2.x_powerConsumption));
this.setState({selectedVarientOne: newArray[0].label, selectedVarientTwo:newArray2[0].label})
But my requirement is i need combination as below like
Output : Black --> 100Watts --> Small|125mm
But as per my above code it is coming like
Black --> 100Watts --> Large|100mm
Can anyone tell me how i can solve this?
Ok, I'm assuming that you want to match the array of objects to the main object
I just use a nest of for loops to see if values from an array(A,B, or C) match up with values from the main object(result) from only the important keys in the result object of course
var A=[{"label":"100Watts","value":"100Watts"},{"label":"135Watts","value":"135Watts"}]
var B=[{"label":"Large|100cm","value":"Large|100cm"},{"label":"Small|125mm","value":"Small|125mm"}]
//now for function to correlate data(sry for late answer was afk lol)
function attribute(arr,result){
const necessary_keys=["x_powerConsumption","x_size","x_color"]
var toReturn=[] //array with output to return
for(let i=0;i<arr.length;i++){
var arrValues=Object.values(arr[i]) //eg: A[0] would be ["100Watts","100Watts"]
for(let j=0;j<result.length;j++){
var resultValues=Object.keys(result[j])
.filter(key=>necessary_keys.includes(key))
.map(key=>result[j][key]) //result[0] would be ["100Watts","Small|125mm","Black"]
if(resultValues.some(value=>arrValues.includes(value))){
toReturn[i]=resultValues //["100Watts","Small|125mm","Black"] for arr[0]
}
}
}
return toReturn //all indexes with undefined dont correlate with result in any of its values
}
//now to use the function
let newArray=attribute(A,result)
let newArray2=attribute(B,result)
console.log("values from A:",newArray)
console.log("values from B:",newArray2)
<script>
var result=[
{
"dynamicPropertyMapLong": {
"sku-Equipment_x_color": 1,
"sku-Equipment_x_size": 1,
"sku-Equipment_x_powerConsumption": 3
},
"x_UAE_installationPrice": 0,
"bundleLinks": [],
"largeImage": null,
"smallImage": null,
"listVolumePrice": null,
"onlineOnly": false,
"listPrices": {
"aed": 100,
"loyaltyProgram": null
},
"configurationMetadata": [],
"largeImageURLs": [],
"x_skuCreationDate": null,
"productLine": null,
"listVolumePrices": {
"aed": null,
"loyaltyProgram": null
},
"derivedSalePriceFrom": "aed",
"model": null,
"x_powerConsumption": "100Watts",
"barcode": null,
"salePriceEndDate": null,
"images": [],
"unitOfMeasure": null,
"primaryMediumImageURL": null,
"dynamicPropertyMapBigString": {},
"active": true,
"x_promotionDetails": "5 Percent Off: 5OFF5",
"thumbImageURLs": [],
"mediumImageURLs": [],
"primarySourceImageURL": null,
"x_description": null,
"sourceImageURLs": [],
"primarySmallImageURL": null,
"x_autoShipPrice": 0,
"productFamily": null,
"primaryThumbImageURL": null,
"nonreturnable": false,
"x_loyaltyLevel": "LEVEL2",
"displayName": "Three variant sku1",
"salePrices": {
"aed": null,
"loyaltyProgram": null
},
"primaryFullImageURL": null,
"productListingSku": null,
"primaryLargeImageURL": null,
"derivedOnlineOnly": false,
"smallImageURLs": [],
"thumbnailImage": null,
"saleVolumePrices": {
"aed": null,
"loyaltyProgram": null
},
"x_size": "Small|125mm",
"saleVolumePrice": null,
"salePriceStartDate": null,
"quantity": null,
"salePrice": null,
"fullImageURLs": [],
"x_isonSale": "Y",
"variantValuesOrder": {},
"x_color": "Black",
"soldAsPackage": true,
"listingSKUId": null,
"x_SAR_installationPrice": 0,
"repositoryId": "300003-1",
"derivedListPriceFrom": "aed",
"x_installationPrice": 0,
"x_costPrice": null,
"configurable": false,
"listPrice": 100
},
{
"dynamicPropertyMapLong": {
"sku-Equipment_x_color": 1,
"sku-Equipment_x_size": 2,
"sku-Equipment_x_powerConsumption": 1
},
"x_UAE_installationPrice": 0,
"bundleLinks": [],
"largeImage": null,
"smallImage": null,
"listVolumePrice": null,
"onlineOnly": false,
"listPrices": {
"aed": 135,
"loyaltyProgram": null
},
"configurationMetadata": [],
"largeImageURLs": [],
"x_skuCreationDate": null,
"productLine": null,
"listVolumePrices": {
"aed": null,
"loyaltyProgram": null
},
"derivedSalePriceFrom": "aed",
"model": null,
"x_powerConsumption": "135Watts",
"barcode": null,
"salePriceEndDate": null,
"images": [],
"unitOfMeasure": null,
"primaryMediumImageURL": null,
"dynamicPropertyMapBigString": {},
"active": true,
"x_promotionDetails": "5 Percent Off: 5OFF5",
"thumbImageURLs": [],
"mediumImageURLs": [],
"primarySourceImageURL": null,
"x_description": null,
"sourceImageURLs": [],
"primarySmallImageURL": null,
"x_autoShipPrice": 0,
"productFamily": null,
"primaryThumbImageURL": null,
"nonreturnable": false,
"x_loyaltyLevel": "LEVEL2",
"displayName": "sku3",
"salePrices": {
"aed": null,
"loyaltyProgram": null
},
"primaryFullImageURL": null,
"productListingSku": null,
"primaryLargeImageURL": null,
"derivedOnlineOnly": false,
"smallImageURLs": [],
"thumbnailImage": null,
"saleVolumePrices": {
"aed": null,
"loyaltyProgram": null
},
"x_size": "Large|100cm",
"saleVolumePrice": null,
"salePriceStartDate": null,
"quantity": null,
"salePrice": null,
"fullImageURLs": [],
"x_isonSale": "Y",
"variantValuesOrder": {},
"x_color": "Black",
"soldAsPackage": true,
"listingSKUId": null,
"x_SAR_installationPrice": 0,
"repositoryId": "300003-3",
"derivedListPriceFrom": "aed",
"x_installationPrice": 0,
"x_costPrice": null,
"configurable": false,
"listPrice": 135
}
]
</script>
Assuming the other answer is correct, here is a shorter version:
result.map(({x_powerConsumption, x_size, x_color}) => ([
A.find(el => el.label === x_powerConsumption).value,
B.find(el => el.label === x_size).value,
C.find(el => el.label === x_color).value
]))
Example:
const A = [{ "label": "100Watts", "value": "100Watts" }, { "label": "135Watts", "value": "135Watts" }];
const B = [{ "label": "Large|100cm", "value": "Large|100cm" }, { "label": "Small|125mm", "value": "Small|125mm" }];
const C = [{ "label": "Black", "value": "Black" }, { "label": "Black", "value": "Black" }];
const result = [
{ "x_powerConsumption": "100Watts", "x_size": "Small|125mm", "x_color": "Black" },
{ "x_powerConsumption": "135Watts", "x_size": "Large|100cm", "x_color": "Black" }
];
console.log(result.map(({x_powerConsumption, x_size, x_color}) => ([
A.find(el => el.label === x_powerConsumption).value,
B.find(el => el.label === x_size).value,
C.find(el => el.label === x_color).value
])));

Map an dynamic array in array js

I have an array(it isn't final version, the array is dynamic)
[{
"TemplateName": "C__01",
"Template": "<div><h1>Hello world!</h1><div id='C__01__body'></div></div>",
"TemplateBody": "body",
"TemplateChildren": [{
"TemplateName": "C__02",
"Template": "<p>Hello1</p>",
"TemplateBody": null,
"TemplateChildren": [{
"TemplateName": "C__03",
"Template": "<p>Hello2</p>",
"TemplateBody": null,
"TemplateChildren": [{
"TemplateName": "C__04",
"Template": "<p>Hello3</p>",
"TemplateBody": null,
"TemplateChildren": null
}, {
"TemplateName": "C__05",
"Template": "<p>Hello4</p>",
"TemplateBody": null,
"TemplateChildren": null
}]
}]
}]
}];
I'm not looking for a field, I just need to map each array in array
const parse = arr => {
arr.map(item => {
console.log(item);
if (item.TemplateChildren) {
parse(item.TemplateChildren);
} else {
return [];
}
});
}

Categories