Remove object from nested array with recursion - arrays

I'm working with vue-draggable for creating a navigation menu. The result array could have N deep levels.
I want to remove an object by it's id.
The array looks like:
[
{
"id": 1,
"name": "Viedma",
"slug": "viedma",
"children": []
},
{
"id": 6,
"name": "Cultura",
"slug": "Cultura",
"children": [
{
"id": 2,
"name": "Rio Negro",
"slug": "rio-negro",
"children": [
{
"id": 4,
"name": "Edictos",
"slug": "edictos",
"children": []
},
{
"id": 5,
"name": "Deportes",
"slug": "deportes",
"children": []
}
]
}
]
},
{
"id": 3,
"name": "Policiales",
"slug": "policiales",
"children": []
}
]
I've tried the solution from remove object from nested array but since I have an array instead of a main object it doesn't work.
Please note that I'm using vue 3 with composition API.
This is what I have so far. The remove() method is called from UI
setup(props, context) {
const resources = ref(props.data)
const removeFromTree = (parent, childNameToRemove) => {
parent.children = parent.children
.filter(function(child){ return child.name !== childNameToRemove})
.map(function(child){ return removeFromTree(child, childNameToRemove)})
return parent
}
const remove = (element) => {
var tree = [...resources.value]
resources.value = removeFromTree(tree, element.name)
}
return {
resources,
remove
}
}
BTW, If parent is removed, all it's children should be removed too.

Your function takes parent as an object but you passing tree as an array. You can do like this
function removeItemByName(items, itemName) {
return items.filter(item => item.name !== itemName)
.map(item => {
item.children = removeItemByName(item.children, itemName)
return item
})
}
const input = [
{
"id": 1,
"name": "Viedma",
"slug": "viedma",
"children": []
},
{
"id": 6,
"name": "Cultura",
"slug": "Cultura",
"children": [
{
"id": 2,
"name": "Rio Negro",
"slug": "rio-negro",
"children": [
{
"id": 4,
"name": "Edictos",
"slug": "edictos",
"children": []
},
{
"id": 5,
"name": "Deportes",
"slug": "deportes",
"children": []
}
]
}
]
},
{
"id": 3,
"name": "Policiales",
"slug": "policiales",
"children": []
}
]
console.log(removeItemByName(input, 'Policiales'))
console.log(removeItemByName(input, 'Deportes'))

Related

Angular: Get parent and specific child from JSON

I have this object:
elements120: {
"data": {
"name": "120",
"type": "120"
},
"children": [
{
"data": {
"name": "120A",
"type": "120A"
},
"children": []
},
{
"data": {
"name": "120B",
"type": "120B"
},
"children": []
},
{
"data": {
"name": "120C",
"type": "120C"
},
"children": []
}
]
}
I need to make some new Json as these below:
Json 1:
filtered120A{
"data": {
"name": "120",
"type": "120"
},
"children": [
{
"data": {
"name": "120A",
"type": "120A"
},
"children": []
}
]
}
Json 2:
filtered120B{
"data": {
"name": "120",
"type": "120"
},
"children": [
{
"data": {
"name": "120B",
"type": "120B"
},
"children": []
}
]
}
Json 3:
filtered120C{
"data": {
"name": "120",
"type": "120"
},
"children": [
{
"data": {
"name": "120C",
"type": "120C"
},
"children": []
}
]
}
I tried to do this in order to get only the first children node and delete the others (it's the only way it works me). For 120B and 120C i put as first child the value of the node that I needed for each case
this.filtered120A = utils.deepClone(this.elements120);
this.filtered120B = utils.deepClone(this.elements120);
this.filtered120C = utils.deepClone(this.elements120);
this.filtered120A = this.filtered120A.filter((element) => {
delete element.children[1];
delete element.children[2];
return true;
});
this.filtered120B = this.filtered120B.filter((element) => {
element.children[0] = element.children[1];
delete element.children[1];
delete element.children[2];
return true;
});
this.filtered120C = this.filtered120C.filter((element) => {
element.children[0] = element.children[2];
delete element.children[1];
delete element.children[2];
return true;
});
It works, but the code is not very elegant. I would like to know if there is any other better alternative.
Here you go:
function getOutputs(input) {
const outputs = [];
for (const child of input.children) {
outputs.push({
"data": {
"name": input.data.name,
"type": input.data.type
},
"children": [child]
});
}
return outputs;
}
const inputs = {
"data": {
"name": "120",
"type": "120"
},
"children": [
{
"data": {
"name": "120A",
"type": "120A"
},
"children": []
},
{
"data": {
"name": "120B",
"type": "120B"
},
"children": []
},
{
"data": {
"name": "120C",
"type": "120C"
},
"children": []
}
]
};
const outputs = getOutputs(inputs);
console.log(outputs[0]); // output1
console.log(outputs[1]); // output2
console.log(outputs[2]); // output3

Cypress intercept nested array and object and asserts it value

I am trying to assert value's in a requestbody which I have intercepted with cypress.
The values I need to assert are "name": "NewName", and "title": "STUB1-Draft" you can see in the requestbody example that I have attached.
My testscript in Cypress:
it.only('Check the requestbody', function () {
cy.intercept('PUT', '**/api/assessmenttest/**', req => {
req.reply({ statusCode: 200 });
}).as('NewSectionAndItem');
cy.wait('#NewSectionAndItem')
.its('request.body.test')
.its('testParts')
.its('testSections')
.its('name')
.should('include', 'NewName');
//cy.wait('#NewSectionAndItem').its('request.body.testParts').expect(arr_obj[1].name).to.equal('NewName')
The request body look like the following:
{
"structureStatistics": {
"testPartCount": 1,
"testSectionCount": 6,
"itemCount": 23
},
"name": "BIMMA",
"title": "OTAP",
"correctionInstructionsUrl": "C:Stub/FakePath/For/Cypress",
"correctionInstructionAppendices": [],
"testParts": [
{
"testSections": [
{
"order": 1,
"name": "Tekst 1 Looking for the one? ",
"itemReferences": [
{
"itemId": "55eb5a28-24d8-4705-b465-8e1454f73ac8",
"weight": 11,
"neutralisationType": "NoNeutralisation",
"itemSummary": {
"id": "55eb5a28-24d8-4705-b465-8e1454f73ac8",
"title": "H-E-T1-1"
}
}
],
"id": "5c3eef2d-1094-4b9e-84c1-f184956f87fa"
},
{
"id": "ffaebc93-0bf6-4f75-944a-f61345a7be90",
"name": "NewName",
"itemReferences": [
{
"itemId": "58a29037-c92c-48f6-a7c3-a2f94e288992",
"weight": 0,
"neutralisationType": "NoNeutralisation",
"itemSummary": {
"id": "58a29037-c92c-48f6-a7c3-a2f94e288992",
"title": "STUB1-Draft",
"state": "Draft"
}
}
]
},
{
"order": 2,
"name": "Tekst 2 The fruit Iron Ox bears",
"itemReferences": [
{
"itemId": "abfc0811-26c7-4d9d-b3cc-0c920e5af259",
"weight": 2,
"neutralisationType": "NoNeutralisation",
"itemSummary": {
"id": "abfc0811-26c7-4d9d-b3cc-0c920e5af259",
"title": "H-E-T2-2"
}
},
{
"itemId": "3cfda5e0-0d64-44ef-8a4d-21f37484c024",
"weight": 12,
"neutralisationType": "NoNeutralisation",
"itemSummary": {
"id": "3cfda5e0-0d64-44ef-8a4d-21f37484c024",
"title": "H-E-T2-3"
}
},
{
"itemId": "19ba8a53-9755-4beb-8f69-edd107b80230",
"weight": 1,
"neutralisationType": "NoNeutralisation",
"itemSummary": {
"id": "19ba8a53-9755-4beb-8f69-edd107b80230",
"title": "H-E-T2-4"
}
},
{
"itemId": "3f5b7b81-df1f-4f01-8165-cb2226d9044d",
"weight": 1,
"neutralisationType": "NoNeutralisation",
"itemSummary": {
"id": "3f5b7b81-df1f-4f01-8165-cb2226d9044d",
"title": "H-E-T2-5"
}
}
],
"id": "00f7455e-6d7d-4311-80cd-eff45c83ef2c"
},
{
"order": 3,
"name": "Tekst 3 How to live like a tramp",
"itemReferences": [
{
"itemId": "7e2d568c-4cde-4500-9c6b-c09f246155e4",
"weight": 1,
"neutralisationType": "NoNeutralisation",
"itemSummary": {
"id": "7e2d568c-4cde-4500-9c6b-c09f246155e4",
"title": "H-E-T3-6"
}
},
{
"itemId": "87a5bf1c-451a-40b8-802a-53ee842cafcd",
"weight": 1,
"neutralisationType": "NoNeutralisation",
"itemSummary": {
"id": "87a5bf1c-451a-40b8-802a-53ee842cafcd",
"title": "H-E-T3-7"
}
}
],
"id": "390ecc2e-6715-4898-aaea-158e790525a2"
}
],
"navigationMode": "Linear",
"submissionMode": "Individual",
"id": "a546a67c-ac39-4e81-bf03-beb482c920a0"
}
],
"metadataToBePublished": [
"be63002c-dcf8-449f-a0ae-6ba50d4e2712",
"4d70239e-7a6e-47c3-b157-462d6c8c5edc"
],
"created": "2022-07-08T09:00:00+00:00",
"modified": "2022-09-21T23:55:58.6532451+02:00",
"createdBy": {
"id": "a45ea6db-bf04-427d-9354-7081b7592a3d",
"fullName": "Manual Construction"
},
"lastModifiedBy": {
"id": "129a584c-a677-4d9f-b289-019d1815064f",
"fullName": "OZKAN"
},
"id": "300eea01-ee10-4bd9-9356-8aaa933e949c"
}
I could not figure out how I can assert nested arrays and value's, without using deep.equal for the complete request. Thank you indeed!
It basically just looks like a couple of things
an extra test property in the test that's not there in the request
testParts and testSections are arrays (square bracket instead of curly bracket), so you need an index for them
Generally I think this would work
cy.wait('#NewSectionAndItem')
.its('request.body')
.its('testParts.0')
.its('testSections.1')
.its('name')
.should('include', 'NewName');
The problem is identifying the correct array indexes. testParts has only one element, so 0 is the only index option there.
To find the testSection index, create a dummy .json file in VS Code (or other editor) paste in the json from above and use the collapse toggles on the left to easily see which index contains the value you seek.
You can use a cy-spok plugin to make a spok assertion to easily check a nested property.
Example use
const spok = require('cy-spok')
// later in your test
cy.wait('#NewSectionAndItem')
.its('request.body')
.should(spok({
test: {
testParts: {
testSections: {
name: 'NewName',
title: 'STUB1-Draft'
}
}
}
});

How can I check duplicate and remove object in array object? [duplicate]

This question already has answers here:
How can I access and process nested objects, arrays, or JSON?
(31 answers)
Closed 4 months ago.
How can I find duplicate and remove object have id: 3 and just keep id: 3 in children of id: 2 ?
I have one array object like this:
const data = [
{
"id": 1,
"name": ABC,
"parentID": null,
"children": [
{
"id": 2,
"name": ASD,
"parentID": 1,
"children": [
{
"id": 3,
"name": AS,
"parentID": 2,
"children": []
}
]
}
]
},
{
"id": 3,
"name": AS,
"parentID": 2,
"children": []
},
{
"id": 4,
"name": ASC,
"parentID": null,
"children": []
}
]
I want to write a function for search and remove object id 3, Can I do that by recursive ?
Output:
const data = [
{
"id": 1,
"name": ABC,
"parentID": null,
"children": [
{
"id": 2,
"name": ASD,
"parentID": 1,
"children": [
{
"id": 3,
"name": AS,
"parentID": 2,
"children": []
}
]
}
]
},
{
"id": 4,
"name": ASC,
"parentID": null,
"children": []
}
]
Do you any idea for this issues ?
Thanks for your help 🥰
A simple iterative recursion should resolve this problem. You have to store a list of unique ids that represents each item in the data tree, and use these keys to check if such an item has been traversed or not.
type DataType = {
id: number;
name: string;
parentID: number | null;
children: DataType[];
};
function filterRecursive(collection: DataType[], keys: Record<number, true> = {}) {
const result: DataType[] = [];
for(const item of collection) {
if(item.id in keys === false) {
keys[item.id] = true;
result.push({
...item,
children: filterRecursive(item.children, keys)
});
}
}
return result;
}
const result = filterRecursive(data);
.as-console-wrapper {
top: 0 !important;
max-height: 100% !important;
}
<script src="https://unpkg.com/#babel/standalone#7.18.13/babel.min.js"></script>
<script type="text/babel" data-type="module" data-presets="typescript">
type DataType = {
id: number;
name: string;
parentID: number | null;
children: DataType[];
};
const data = [
{
"id": 1,
"name": 'ABC',
"parentID": null,
"children": [
{
"id": 2,
"name": 'ASD',
"parentID": 1,
"children": [
{
"id": 3,
"name": 'AS',
"parentID": 2,
"children": []
}
]
}
]
},
{
"id": 3,
"name": 'AS',
"parentID": 2,
"children": []
},
{
"id": 4,
"name": 'ASC',
"parentID": null,
"children": []
}
];
function filterRecursive(collection: DataType[], keys: Record<number, true> = {}) {
const result: DataType[] = [];
for(const item of collection) {
if(item.id in keys === false) {
keys[item.id] = true;
result.push({
...item,
children: filterRecursive(item.children, keys)
});
}
}
return result;
}
const result = filterRecursive(data);
console.log(JSON.stringify(result, null, 4));
</script>

Filter an array of obj based on another array value

I have an array of object like this :
[
{
"url": "https://recipes-gatsby-react.netlify.app/",
"stack": [
{
"id": 1,
"title": "GatsbyJs"
},
{
"id": 2,
"title": "React"
},
{
"id": 3,
"title": "GraphQl"
}
],
"id": "Project_1",
"featured": false,
"title": "Gatsby recipes app"
},
{
"url": "https://resort-react-mr.netlify.app",
"stack": [
{
"id": 4,
"title": "React"
},
{
"id": 5,
"title": "Contentful"
}
],
"id": "Project_2",
"featured": false,
"title": "react resort"
},
{
"url": "https://color-generator-react-mr.netlify.app/",
"stack": [
{
"id": 6,
"title": "React"
}
],
"id": "Project_3",
"featured": false,
"title": "color generator"
},
{
"url": "",
"stack": [
{
"id": 7,
"title": "React Native"
},
{
"id": 8,
"title": "Firebase"
}
],
"id": "Project_4",
"featured": false,
"title": "Book-Worm"
},
{
"url": "",
"stack": [
{
"id": 9,
"title": "React Native"
},
{
"id": 10,
"title": "Firebase"
},
{
"id": 11,
"title": "Stripe"
},
{
"id": 12,
"title": "Google Api"
}
],
"id": "Project_5",
"featured": false,
"title": "Delivery App"
},
{
"url": "https://cocktails-react-app-mr.netlify.app/",
"stack": [
{
"id": 13,
"title": "React"
}
],
"id": "Project_6",
"featured": false,
"title": "Cocktails App"
},
{
"url": "https://www.ideacasaitalia.it/index.php",
"stack": [
{
"id": 14,
"title": "Prestashop"
}
],
"id": "Project_7",
"featured": false,
"title": "Idea Casa Italia"
}
]
and I have another (simple) array like this one for example
["react","prestashop"]
I would like to filter the first array based on STACK key on the value of the second array, i.e. I would like to be returned all elements that have at least one element of the array (variable).
I have come to this
const filter = value => {
const newProj = relProjects.filter(obj =>
obj.stack.some(st => st.title.toLowerCase().includes(value))
)
setProjRel(newProj)
}
console.log(filter(["react","prestashop"])
however in this way I can only get the elements that contain all the elements of the array. Instead I would like to have returned all the elements that have AT LEAST 1 stack of the ones I passedThanks to who will answer me
Using Array#filter and Array#includes
Filter through the data array. With the predicate being that the stack array has at least one item that is included in the matches array
const data = [{"url":"https://recipes-gatsby-react.netlify.app/","stack":[{"id":1,"title":"GatsbyJs"},{"id":2,"title":"React"},{"id":3,"title":"GraphQl"}],"id":"Project_1","featured":false,"title":"Gatsby recipes app"},{"url":"https://resort-react-mr.netlify.app","stack":[{"id":4,"title":"React"},{"id":5,"title":"Contentful"}],"id":"Project_2","featured":false,"title":"react resort"},{"url":"https://color-generator-react-mr.netlify.app/","stack":[{"id":6,"title":"React"}],"id":"Project_3","featured":false,"title":"color generator"},{"url":"","stack":[{"id":7,"title":"React Native"},{"id":8,"title":"Firebase"}],"id":"Project_4","featured":false,"title":"Book-Worm"},{"url":"","stack":[{"id":9,"title":"React Native"},{"id":10,"title":"Firebase"},{"id":11,"title":"Stripe"},{"id":12,"title":"Google Api"}],"id":"Project_5","featured":false,"title":"Delivery App"},{"url":"https://cocktails-react-app-mr.netlify.app/","stack":[{"id":13,"title":"React"}],"id":"Project_6","featured":false,"title":"Cocktails App"},{"url":"https://www.ideacasaitalia.it/index.php","stack":[{"id":14,"title":"Prestashop"}],"id":"Project_7","featured":false,"title":"Idea Casa Italia"}];
const matches = ["react", "prestashop"];
const filtered = data.filter(({ stack }) => stack.filter(({ title }) => matches.includes(title.toLowerCase())).length > 0);
console.log(filtered);

I can't convert object to an array

I am trying to make a shopping cart API route and I am stuck with this problem because when I am using this statement $carts = \Cart::session($session)->getContent();
I get an object like this:
"cart": {
"1": {
"id": 1,
"name": "Tort cu biscuiți",
"price": 20,
"quantity": "1",
"attributes": {
"image_path": "http://127.0.0.1:8000/storage/images/AkiGKJdxjKNtyoVI034RPL1drLsMntUxLfzqZplV.jpeg"
},
"conditions": []
},
"2": {
"id": 2,
"name": "Tort cu biscuiți",
"price": 20,
"quantity": 2,
"attributes": {
"image_path": "http://127.0.0.1:8000/storage/images/IkAhenLttHWaRD58hNZ460ykWCq7q1sih3vI9H5V.jpeg"
},
"conditions": []
}
}
and I want to convet this to be array of objects. I tryied $cart->toArray(); and didn't work, also I tiyed (array) $cart and I get this:
"cart": {
"\u0000*\u0000items": {
"1": {
"id": 1,
"name": "Tort cu biscuiți",
"price": 20,
"quantity": "1",
"attributes": {
"image_path": "http://127.0.0.1:8000/storage/images/AkiGKJdxjKNtyoVI034RPL1drLsMntUxLfzqZplV.jpeg"
},
"conditions": []
},
"2": {
"id": 2,
"name": "Tort cu biscuiți",
"price": 20,
"quantity": 2,
"attributes": {
"image_path": "http://127.0.0.1:8000/storage/images/IkAhenLttHWaRD58hNZ460ykWCq7q1sih3vI9H5V.jpeg"
},
"conditions": []
}
}
}
may I know what is the problem?
You can do it manuel like this:
$carts = \Cart::session($session)->getContent();
if ($carts) {
$cartsArray = json_decode($carts);
foreach($cartsArray->cart as &$cart){
$cart = (array) $cart;
}
}
dd($cartsArray);

Resources