Search for matches in an array of objects. JS - javascript

I have the following response from the server. I need to search this answer and compare it in turn with each field.
Example:
My task is that I know for sure that there should be 3 objects and each object has its own value for the type field, this is 'API', 'DEFAULT' or 'X'. How can you make it so that you can search for these three values ​​in the whole object and get an error if one of them is missing?
{
"result": [
{
"id": "54270522",
"key": "1-16UUC93PT",
"type": "API"
},
{
"id": "54270522",
"key": "3-1JOPPEIZI",
"type": "DEFAULT"
},
{
"id": "54270522",
"key": "3-1JOPPEIZI",
"type": "Х"
}
],
"success": true
}

You can first verify that the length is 3 and then loop over all the types and check if each one is present.
const data = {
"result": [
{
"id": "54270522",
"key": "1-16UUC93PT",
"type": "API"
},
{
"id": "54270522",
"key": "3-1JOPPEIZI",
"type": "DEFAULT"
},
{
"id": "54270522",
"key": "3-1JOPPEIZI",
"type": "Х"
}
],
"success": true
};
const requiredTypes = ['API', 'DEFAULT', 'Х'];
const types = new Set(data.result.map(({type})=>type));
const good = data.result.length === 3 && requiredTypes.every(type=>types.has(type));
console.log(good);

In case you would like to also know which value of those 3 are missing:
const check = (obj) => {
if (obj.result.length !== 3) return false;
let validTypes = ['API', 'DEFAULT', 'X'];
obj.result.forEach((r) => {
const index = validTypes.indexOf(r.type);
if (index !== -1) validTypes.splice(index, 1);
})
if (validTypes.length) return `${validTypes.join(', ')} is missing`;
return true;
};
So if you would have something like:
const test = {
"result": [
{
"id": "54270522",
"key": "1-16UUC93PT",
"type": "API"
},
{
"id": "54270522",
"key": "3-1JOPPEIZI",
"type": "DEFAULT"
},
{
"id": "54270522",
"key": "3-1JOPPEIZI",
"type": "X2"
}
],
"success": true
}
and you call check(test) it will return "X is missing". If all three types are present in the object that gets passed into the check function, it will return true. Of course this can be adjusted as you need. More objects, different types etc...

Related

How to group keys from a nested object?

Hya 👋
Suppose we have a dynamic object like so:
[
{
"object": "block",
"id": "089cd0d8-ccbf-4e9e-97a6",
"parent": {
"type": "page_id",
"page_id": "d4b96daf-47a3-4a04-b200"
},
"type": "child_database",
"child_database": {
"title": "Hero"
}
},
{
"object": "page",
"id": "d3022361-96d2-4e15-999e",
"parent": {
"type": "database_id",
"database_id": "089cd0d8-ccbf-4e9e-97a6"
},
},
{
"object": "block",
"id": "a0cba166-1787-4e30-8cc3",
"parent": {
"type": "page_id",
"page_id": "d3022361-96d2-4e15-999e"
},
"type": "heading_1",
"heading_1": {
"rich_text": [
{
"type": "text",
"text": {
"content": "Introduction",
"link": null
},
"plain_text": "Introduction",
"href": null
}
],
}
},
{
"object": "block",
"id": "dbfdd892-8c04-4de3-bf0e",
"parent": {
"type": "page_id",
"page_id": "d3022361-96d2-4e15-999e"
},
"type": "heading_2",
"heading_2": {
"rich_text": [
{
"type": "text",
"text": {
"content": "This is introduction section",
"link": null
},
"plain_text": "This is introduction section",
"href": null
}
],
}
}
]
I would like to reconstruct this object by grouping them based on parent-child like relationship. Since every object has "parent" prop.
The desired result should be like so, where the elements that share the same parent are grouped under child array.
{
"d4b96daf-47a3-4a04-b200": {
"object": "block",
"id": "089cd0d8-ccbf-4e9e-97a6",
"type": "child_database",
"child": [{
"d3022361-96d2-4e15-999e": {
"object": "page",
"child": [{
"a0cba166-1787-4e30-8cc3": {
"object": "block",
"type": "heading_1",
"heading_1": {
"rich_text": [{
"type": "text",
"text": {
"content": "Introduction",
"link": null
},
"plain_text": "Introduction",
"href": null
}]
}
}
},
{
"dbfdd892-8c04-4de3-bf0e": {
"object": "block",
"type": "heading_1",
"heading_2": {
"rich_text": [{
"type": "text",
"text": {
"content": "This is introduction section",
"link": null
},
"plain_text": "This is introduction section",
"href": null
}]
}
}
}
]
}
}]
}
}
Current workaround
/**
* Generator that traverses through nested object
*/
function* traverse(xs: any[] = []): any {
for (let x of xs) {
yield x
yield* traverse(x.child || [])
}
}
/**
* If the property exists in the nested object, then return node
*/
const deepFind = (block: any, pred: any) => (obj: any) => {
for (let node of traverse([obj])) {
if (pred(node)) {
return node
}
}
}
const findById = (block: any) => (obj: any) => deepFind(block, (o: any) => o[block.id])(obj)
export default async function group(pages: Page[]) {
// stuck here 🙏
}
You can do this linearly: create a Map id=>object, iterate the list, if the parent is already on the map, add your object to the parent.child, otherwise create a placeholder object with the parent's id.
let m = new Map()
for (let obj of data) {
let dummy = {id: 'dummy', child: []}
let oid = obj.id
m.set(oid, {...dummy, ...obj, ...m.get(oid)})
let pid = obj.parent.page_id // or whatever depending on type
m.set(pid, m.get(pid) ?? dummy)
m.get(pid).child.push(obj)
}
In the end, the m.values() will contain a flat list of objects with child arrays properly populated.

Create a tree structure from an array with parent-child references

I am trying to alter the json in snippet to a tree structure just like in https://www.primefaces.org/primeng/#/treetable (below is the sample i expect too). I understand it involves recursion but I ain't sure how to deeply link each.
The output i expect is something like below. The json whose parent is true becomes the root. If the root has values, the json corresponding to id of the value is pushed to children array with a json object "data". Again if that json has values, the json correspond to the id of value is pushed to children array with a json object "data and so on.
The code i have written is just a initial phase. Need help on how nesting can be done through iteration.
[
{
"data": {
"parent": true,
"id": "C001",
"type": "Folder",
"values": [
{
"id": "P001",
"type": "File"
}
]
},
"children": [
{
"data": {
"parent": false,
"id": "P001",
"type": "File",
"values": [
{
"id": "P002",
"type": "Image"
}
]
},
"children": [
{
"data": {
"parent": false,
"id": "P002",
"type": "Image",
"values": [
]
}
}
]
}
]
},
{
"data": {
"parent": true,
"id": "S000",
"type": "Something",
"values": [
]
}
}
]
var junkdata=[
{
"parent": false,
"id": "P001",
"type":"File",
"values": [
{
"id": "P002",
"type": "Image"
}
]
},
{
"parent": true,
"id": "C001",
"type": "Folder",
"values": [
{
"id": "P001",
"type": "File"
}]
},
{
"parent": false,
"id": "P002",
"type": "Image",
"values":[]
},
{
"parent": true,
"id": "S000",
"type": "Something",
"values":[]
}];
var parentDatas=junkdata.filter((x)=>x.parent==true);
if(parentDatas.length>0){
var finalResponse=parentDatas.map((parentData)=>{
var resultJson={};
resultJson.data=parentData;
if(parentData.values.length>0){
resultJson.children=[];
for(var i of parentData.values){
var child=junkdata.find((x)=>x.id==i.id);
if(child){
var jsonObj={};
jsonObj.data=child;
resultJson.children.push(jsonObj);
}
}
}
return resultJson;
})
}
console.log(JSON.stringify(finalResponse));
Basically, we can start with this to process the root nodes:
let tree = yourData.filter(x => x.parent).map(process);
where process is the recursive function that processes a given node:
let process = node => ({
id: node.id,
type: node.type,
children: node.values.map(x => process(
yourData.find(y => y.id === x.id)))
});
For each id in node.values, it locates a node with that id and recursively calls process on it. Once all child nodes are dealt with, process collects them into an array and returns the newly formatted object.
This is the general recursion pattern for working with graph-alike structures, where you have "nodes" somehow connected to other "nodes":
function F (N: node) {
for each node M which is connected to N {
F (M) <--- recursion
}
result = do something with N
return result
}

Javascript push multiple objects into an empty object

I am trying to achieve a data structure in javascript that looks like this:
settings: {
{ "key": "Language", "value": "en" },
{ "key": "Language", "value": "en" }
}
The amount of keys is variable and needs to be iterated over. I thought I could do it with an array but the [0] numbers are getting in the way.
This is what i have now:
convertSettingsToApiSaveFormat(values) {
const keys = Object.keys(values);
const items = Object.values(values);
const valuesToSend = keys.map((key, i) => {
return { key, value: items[i] };
});
return { settings: [valuesToSend] };
}
}
Which returns:
any help is much appreciated!
First of all this is an invalid data structure
settings: {
{ "key": "Language", "value": "en" },
{ "key": "Language", "value": "en" }
}
JavaScript object is bascally key value pair you can see the bellow two objects dont have and key.
Either it can be like this
settings: {
"someKey": { "key": "Language", "value": "en" },
"someKey2": { "key": "Language", "value": "en" }
}
or a simple JS array
settings: [
{ "key": "Language", "value": "en" },
{ "key": "Language", "value": "en" }
]
You're placing valuesToSend inside an array - remove it, and you'll get your desired output*:
return { settings: valuesToSend };
* The result you currently want is invalid - this, however, is valid:
settings: [
{ "key": "Language", "value": "en" },
{ "key": "Language", "value": "en" }
}

Convert one Multidimensional JSON array to another

I have the following input object
{
"id": 1,
"isLeaf": false,
"name": "New rule",
"pid": 0,
"dragDisabled": true,
"children": [
{
"id": "new1",
"value": "data1",
"then": false,
"type": "set",
"forEach": false,
"pid": 1
},
{
"id": "new2",
"value": "data2",
"then": true,
"type": "if",
"forEach": false,
"pid": 1,
"children": [
{
"id": "new3",
"type": "Then",
"enableElse": true,
"pid": "new2",
"children": [
{
"id": "new5",
"value": "data3",
"then": false,
"type": "fuzzy_search",
"forEach": false,
"pid": "new3"
}
]
},
{
"id": "new4",
"type": "Else",
"enableElse": true,
"pid": "new2",
"children": [
{
"id": "new6",
"value": "data4",
"then": false,
"type": "return",
"forEach": false,
"pid": "new4"
}
]
}
]
}
]
}
I need to convert it into the following json
[
{
"id": "new1",
"condition": "data1"
},
{
"id": "new2",
"condition": "data2",
"then": [{
"id": "new5",
"condition": "data3"
}],
"else": [{
"id": "new6",
"condition": "data4"
}]
}
]
I have to recursively iterate through all existing inner child array of the input json array to formulate the output.
Following is the partially implemented code for the functionality.
ruleJSONFormatter = (request, parentItem, innerJSON) => {
try {
var outerObject = request;
if (outerObject.children && outerObject.children.length) {
var innerArray = outerObject.children;
// second iteration with inner children
innerArray.forEach((innerItem, index) => {
let parentObj = {};
let recursiveObj = {}; let thenArray = [];
recursiveObj['condition'] = innerItem.value && innerItem.value != undefined ? innerItem.value.formatedData : {};
recursiveObj['type'] = innerItem.type;
recursiveObj['id'] = innerItem.id;
recursiveObj['pid'] = innerItem.pid;
if (innerItem.children && innerItem.children != undefined && innerItem.children.length) {
switch (innerItem.type) {
case 'if':
recursiveObj['then'] = [];
recursiveObj['else'] = [];
}
if (Object.keys(parentObj).length == 0) {
parentObj = recursiveObj;
} else {
}
ruleJSONFormatter(innerItem, parentItem, parentObj)
} else {
if (Object.keys(parentObj).length == 0)
responseArray.push(innerJSON);
}
});
}
else {
console.log("No Values Inside the Formated Data ")
}
console.log("output-----------");
console.log(JSON.stringify(responseArray));
return responseArray
} catch (error) {
console.log('((((((((((((((((((((((((((', error)
}
}
final output array has a condition key which binds the value key from the input json and 'then' key which contains the multiple successive inner children array which is the success condition for type 'if' object. similar is the case for 'else' key in output
I find it hard to recursively call the same function to generate the desired output. the problem arises when there are deep nesting in the children array.Any help is appreciated.Thanks.

How to access an array of objects inside another array of objects in angular 4

I have a api response that return this :
{
"code": 0,
"message": "hierarchy list",
"payload": [
{
"id": 2,
"name": "nameParent",
"code": "WUcw",
"childsOfPayload": [
{
"id": 5,
"name": "NameChild1",
"code": "ozyW",
"status": "Active",
"childsofChildOfPayload": [
{
"id": 8,
"name": "NameChild2",
"code": "aitq",
"order": 30,
},
]}]}]}
I am trying to get the differents objects in each childs, ChildOfPayload and childOfChildOfpayload.
First I've returned the different name value of payload:
getAllPayloadName() {
this.userService.getName().subscribe(
data => {
this.values= data;
}
);
}
But what must I do to get the name of each child assosiated to the different parent value!
I mean in this case.
NameChild1
NameChild2
I've tried this:
manipulateDataa() {
this.values.subscribe(x => {
x.payload.foreach((y:any) => {
y.childs.foreach((z:any) => {
console.log( z.name)
})
})
})
}
then call it in getAllPayloadName, but still don't work. What could be wrong?
You could do something like this to get your desired output. Here you can read more about forEach loop which I have used.
data = {
"code": 0,
"message": "hierarchy list",
"payload": [
{
"id": 2,
"name": "nameParent",
"code": "WUcw",
"childsOfPayload": [
{
"id": 5,
"name": "NameChild1",
"code": "ozyW",
"status": "Active",
"childsofChildOfPayload": [
{
"id": 8,
"name": "NameChild2",
"code": "aitq",
"order": 30,
},
]}]}]}
names = []
function iterator (obj, namesArr){
Object.keys(obj).forEach(key => {
if(key === "name") {
namesArr.push(obj[key])
} else if(typeof obj[key] === "object") {
iterator(obj[key][0], names)
}
})
}
iterator(data.payload[0], names)
console.log(names)
if the api result structure is strongly type and will not change u can access the child payload name by this line
console.log(JSON.stringify(obj.payload[0].childsOfPayload[0].name));
console.log(JSON.stringify(obj.payload[0].childsOfPayload[0].childsofChildOfPayload[0].name));

Categories

Resources