Related
I have an array of objects and want every object in the array to have the same keys.
var obj1 = {"type": "test", "info": "a lot", "value": 7};
var obj2 = {"value": 5};
var obj3 = {"context": "demo", "info": "very long", "value": 3};
var obj4 = {"info": "no way"};
var dataSet = [obj1,obj2,obj3,obj4];
My attempt is to create an array with all possible keys in the first step.
Then loop through that keys array and update the objects if the key was not found.
keys.forEach(function(a,b){
dataSet.forEach(function(c,d){
//key not found
if(a in c === false)
{
//add key to object
dataSet[b][a] = false;
}
});
});
Howewer, it does not seem to work correctly.
This is my output:
after logic: [
{
"type": false,
"info": "a lot",
"value": 7
},
{
"value": 5,
"info": false
},
{
"context": "demo",
"info": "very long",
"value": false
},
{
"info": "no way",
"context": false
}
]
What am I missing there?
var obj1 = {"type": "test", "info": "a lot", "value": 7};
var obj2 = {"value": 5};
var obj3 = {"context": "demo", "info": "very long", "value": 3};
var obj4 = {"info": "no way"};
var dataSet = [obj1,obj2,obj3,obj4];
var keys = [];
console.log("before logic: ", dataSet);
//Step 1: Fill keys array
dataSet.forEach(function(a,b){
Object.keys(a).forEach(function(c,d)
{
//add keys to array if not already exists
if(!keys.includes(c))
{
keys.push(c);
}
});
});
//Step2: loop through keys array and add key to object if not existing
keys.forEach(function(a,b){
dataSet.forEach(function(c,d){
//key not found
if(a in c === false)
{
//add key to object
dataSet[b][a] = false;
}
});
});
console.log("after logic: ", dataSet);
EDIT:
It would be perfect if the keys are always sorted in the same order too.
You can just collect the keys in a Set using flatMap(), and then assign the missing ones using forEach():
const dataSet = [
{"type": "test", "info": "a lot", "value": 7},
{"value": 5},
{"context": "demo", "info": "very long", "value": 3},
{"info": "no way"}
];
const keys = new Set(dataSet.flatMap(Object.keys));
dataSet.forEach((v) => keys.forEach((k) => v[k] = k in v ? v[k] : false));
console.log(dataSet);
To address the additional request of having the keys in the same order, note that historically, JavaScript object properties were unordered, so relying on the order of object properties in JavaScript is almost never a good idea.
That being said, it's hard to get a fixed order when modifying the existing objects, but doable if you create new objects:
const dataSet = [
{"type": "test", "info": "a lot", "value": 7},
{"value": 5},
{"context": "demo", "info": "very long", "value": 3},
{"info": "no way"}
];
const keys = [...new Set(dataSet.flatMap(Object.keys))];
const result = dataSet.map((v) => keys.reduce((a, k) => ({
...a,
[k]: k in v ? v[k] : false
}), {}));
console.log(result);
You can create a 'template' object from the Set of combined keys and then simply Object.assign to this template from each object. This will give you all the properties in a consistent order.
const dataSet = [
{ "type": "test", "info": "a lot", "value": 7 },
{ "value": 5 },
{ "context": "demo", "info": "very long", "value": 3 },
{ "info": "no way" }
];
const template = Object.fromEntries([...new Set(dataSet.flatMap(o => Object.keys(o)))].map(k => [k, false]));
const result = dataSet.map(o => Object.assign({ ...template }, o));
console.log(result)
Alternatively you can create the template by simply merging all the objects in the data set and overwriting a default value.
const dataSet = [
{ "type": "test", "info": "a lot", "value": 7 },
{ "value": 5 },
{ "context": "demo", "info": "very long", "value": 3 },
{ "info": "no way" }
];
const template = Object.assign({}, ...dataSet);
for (const k of Object.keys(template)) {
template[k] = false;
}
const result = dataSet.map(o => Object.assign({ ...template }, o));
console.log(result)
The problem with your code is basically a typo: You're using the wrong index when you set the key:
dataSet[b][a] = false;
b is the index of the key in keys, not the index of the object in dataSet. You don't need to do that indexing at all, just do:
c[a] = false;
It's much easier to follow what you're doing and such when you use meaningful names for variables rather than a, b, c, and d. Here's your code with some reasonable renaming and with the change described above:
var obj1 = { type: "test", info: "a lot", value: 7 };
var obj2 = { value: 5 };
var obj3 = { context: "demo", info: "very long", value: 3 };
var obj4 = { info: "no way" };
var dataSet = [obj1, obj2, obj3, obj4];
var keys = [];
console.log("before logic: ", JSON.stringify(dataSet, null, 4));
//Step 1: Fill keys array
dataSet.forEach(function (obj) {
Object.keys(obj).forEach(function (key) {
//add keys to array if not already exists
if (!keys.includes(key)) {
keys.push(key);
}
});
});
//Step2: loop through keys array and add key to object if not existing
keys.forEach(function (key) {
dataSet.forEach(function (obj) {
//key not found
if (key in obj === false) {
//add key to object
obj[key] = false;
}
});
});
console.log("after logic: ", JSON.stringify(dataSet, null, 4));
.as-console-wrapper {
max-height: 100% !important;
}
But that code can be much simpler using a Set and modern language features:
const obj1 = { type: "test", info: "a lot", value: 7 };
const obj2 = { value: 5 };
const obj3 = { context: "demo", info: "very long", value: 3 };
const obj4 = { info: "no way" };
const dataSet = [obj1, obj2, obj3, obj4];
const keys = new Set(); // *** Use a set
console.log("before logic: ", dataSet);
// Step 1: Fill keys array
for (const obj of dataSet) {
for (const key of Object.keys(obj)) {
keys.add(key);
}
}
// Step2: loop through keys array and add key to object if not existing
for (const key of keys) {
for (const obj of dataSet) {
if (!(key in obj)) {
obj[key] = false;
}
}
}
console.log("after logic: ", JSON.stringify(dataSet, null, 4));
.as-console-wrapper {
max-height: 100% !important;
}
Robby Cornelissen takes it much further, but I wanted to show using simple loops.
I am preparing an array like this
datas[5] = { "qty_sized": "1", "resolution": "5", "status": "", "order": 1342 };
where [5] is dynamic from response.
I have and object mydata and inside that I have a object items.
I push array to object items, with assign
Object.assign(mydatadata.items, datas);
Now mydata.items has an array set,
`
items{
1 {qty_auth: "", resolution: "4", status: "", order: "1495"},
5 {qty_sized: "1", resolution: "4", status: "", order: "1485"}
}`
Now if qty_auth: "" , from which i need to check if qty_ is empty then remove the array . So expected output is something like this:
Note: qty_ is dynamic here.
items{ 5 {qty_sized: "1", resolution: "4", status: "", order: "1485"} }
and i want to result inside same object mydata.items
I tried something like this
const mydatadata.items = mydata.items.filter((o) =>
Object.keys(o).some((k) => k.startsWith("qty") && o[k])
);
console.log(result);
but its now giving me any output
Using Object#entries, get the key-value pairs of items
Using Array#filter, iterate over the above array
In each iteration, check if the current item has a key starting with qty_ whose value is not empty. You can do this using Object#keys, Array#some, and String#startsWith.
Using Object#fromEntries, convert the filtered pairs to an object again.
const obj = {
items: {
1: {qty_auth: "", resolution: "4", status: "", order: "1495"},
5: {qty_sized: "1", resolution: "4", status: "", order: "1485"}
}
};
obj.items = Object.fromEntries(
Object.entries(obj.items)
.filter(([_, item]) =>
Object.keys(item).some(key => key.startsWith('qty_') && item[key])
)
);
console.log(obj);
You're talking about an array, but using curly brackets instead of square brackets. For filter() to work it would have to look like:
mydata = {
items: [
{qty_auth: "", resolution: "4", status: "", order: "1495"},
{qty_sized: "1", resolution: "4", status: "", order: "1485"}
]
}
Assuming it is an actual array there's still a problem with "const mydatadata.items", or at least it throws an error for me because mydatadata is not initialized. Unless it's a typo and it should be mydata, but then you'd be redeclaring it. So depending on what you want:
mydata.items = mydata.items.filter((o) =>
Object.keys(o).some((k) => k.startsWith("qty") && o[k])
);
or
let mydatadata = {};
mydatadata.items = mydata.items.filter((o) =>
Object.keys(o).some((k) => k.startsWith("qty") && o[k])
);
Furthermore you're storing the result in mydatadata but you're logging the variable result.
So depending on the previous answer:
console.log(mydatadata);
or
console.log(mydata);
Here's a fiddle: https://jsfiddle.net/b57qa82d/
You should probably just be using an array rather than an object. It's not really clear from your question what structure you need as you keep changing the terminology to describe your data. For example: "Now mydata.items has an array set" but your code says that it should be object with keys, not an array.
So I suggest: get your data in an array, and filter it by iterating over each object's entries and checking to see if any of the keys starting with "qty" has a value that isn't an empty string. You can then assign that filtered array to myObject.items.
const data = [
{ "qty_sized": "0", "resolution": "5", "status": "", "order": 2 },
{ "qty_auth": "", "resolution": "5", "status": "", "order": 3 },
{ "qty_auth": "1", "resolution": "5", "status": "", "order": 1342 },
{ "qty_sized": "", "resolution": "2", "status": "", "order": 1 },
{ "qty_sized": "1", "resolution": "1", "status": "", "order": 142 }];
const filtered = data.filter(obj => {
return Object.entries(obj).find(([key, value]) => {
return key.startsWith('qty') && value;
});
});
const myObject = { items: filtered };
console.log(myObject);
Additional documentation
Object.entries
find
I would like to search through multi layered nested object in javascript. The number of layers is dynamic.Not fixed.
Let's say I have an object like this.
data={
"_index": "sample_data_logs",
"_type": "_doc",
"_id": "lDMTgnEBbYNxp5GHN-gj",
"_version": 1,
"_score": 7.6343846,
"_source": {
"agent": "Mozilla/4.0",
"bytes": 6948,
"clientip": "172.3.128.226",
"extension": "",
"geo": {
"srcdest": "IN:BY",
"src": "IN",
"dest": "BY",
"coordinates": {
"lat": 41.92076333,
"lon": -71.49138139
}
},
"host": "www.host.co",
"index": "sample_data_logs",
"ip": "172.3.128.226",
"machine": {
"ram": 5368709120,
"os": "win 8"
},
"memory": null,
"phpmemory": null,
"request": "/apm",
"response": 200,
"tags": [
"success",
"security"
],
"timestamp": "2020-04-13T11:05:05.551Z",
"url": "https://www.elastic.co/downloads/apm",
"utc_time": "2020-04-13T11:05:05.551Z"
}
}
keys= ["_index","bytes","os","tags"];
And I have an array of key values to find or filter in data.
How can I do that?
Using lodash I have tried
_.pick(data_, keys);
I don't get the expected results which should be:
{
"_index": "sample_data_logs",
"bytes": 6948,
"os": "win 8",
"tags": [
"success",
"security"
]
}
What is the best way of doing this? can it be done in vanilla js?
You need to traverse your data recursively, like this:
Explanation:
We have a function traverse that takes:
an object (called data),
a list of keys (called keys),
and an object that contains the current result (the found key/value pairs called result)
In the traverse function, we go over the first level keys of object data (using Object.keys(data)) and we check if each of them is in the keys list, and if it is then we add that key/value pair to the result and go to the next one.
But if it is not in the keys, then we need to check if that key is a nested object, so we do that with this conditions:
if (
data[k] &&
typeof data[k] === "object" &&
Object.keys(data[k]).length > 0
)
The first one (data[k]) is used to rule out null and undefined
The second one (typeof data[k] === "object") is used to check if the value is an object
The third condition is used to rule out native objects like Date
And if it is a nested object, then we call the traverse (recursive) again
let data = {
_index: "sample_data_logs",
_type: "_doc",
_id: "lDMTgnEBbYNxp5GHN-gj",
_version: 1,
_score: 7.6343846,
_source: {
agent: "Mozilla/4.0",
bytes: 6948,
clientip: "172.3.128.226",
extension: "",
geo: {
srcdest: "IN:BY",
src: "IN",
dest: "BY",
coordinates: {
lat: 41.92076333,
lon: -71.49138139,
},
},
host: "www.host.co",
index: "sample_data_logs",
ip: "172.3.128.226",
machine: {
ram: 5368709120,
os: "win 8",
},
memory: null,
phpmemory: null,
request: "/apm",
response: 200,
tags: ["success", "security"],
timestamp: "2020-04-13T11:05:05.551Z",
url: "https://www.elastic.co/downloads/apm",
utc_time: "2020-04-13T11:05:05.551Z",
},
};
let keys = ["_index", "bytes", "os", "tags"];
function traverse(data, keys, result = {}) {
for (let k of Object.keys(data)) {
if (keys.includes(k)) {
result = Object.assign({}, result, {
[k]: data[k]
});
continue;
}
if (
data[k] &&
typeof data[k] === "object" &&
Object.keys(data[k]).length > 0
)
result = traverse(data[k], keys, result);
}
return result;
}
result = traverse(data, keys);
console.log(result);
You can use :
const object1 = {
a: 'somestring',
b: 42
};
for (let [key, value] of Object.entries(object1)) {
if (key === target) {// do somethings}
}
If the keys is equal to your need, you can perform your treatment ?
Hope it's help
I receive a JSON result message in the following format from an old database query that I do not have the ability to change at this time:
{
"vsm1": "2429",
"vsm2": "2488",
"vsm3": "1968",
"vsm4": "",
"vsm5": "",
"vsm6": "",
"vsm7": "",
"vsm8": "",
"vsm9": "",
"vsm10": "",
"color1": "5",
"color2": "4",
"color3": "4",
"color4": "0",
"color5": "0",
"color6": "0",
"color7": "0",
"color8": "0",
"color9": "0",
"color10": "0",
"p1mtime": "1549296004",
"p2mtime": "1549296009",
"p3mtime": "1549296014",
"p4mtime": "",
"p5mtime": "",
"p6mtime": "",
"p7mtime": "",
"p8mtime": "",
"p9mtime": "",
"p10mtime": "",
"inch1": "",
"inch2": "",
"inch3": "",
"inch4": "",
"inch5": "",
"inch6": "",
"inch7": "",
"inch8": "",
"inch9": "",
"inch10": ""
}
I would like to re-format it to a more useable object, like so:
{ id: 1, vsm: 2429, color: 5, pmtime: 1549296004, inch: 0 }
{ id: 2, vsm: 2488, color: 4, pmtime: 1549296009, inch: 0 }
{ id: 3, vsm: 1968, color: 4, pmtime: 1549296014, inch: 0 }
...and so on.
The incoming data is currently limited to ten of each 'section' (vsm1, vsm2, ...vsm10, color1, color2, ...color10, etc.), so a static loop of some sort over the ten elements in each section is how i started, but seemed rather ugly and certainly not flexible.
A smart snippet that would handle n-number of elements in each section would be even better just in case the data goes beyond ten elements, or drops to just three (due to absence of data or pruned data).
I'm thinking of something along the lines of using .forEach(), but admittedly my JSON / Object manipulation skills are rather poor, so I turn to the community in the hope that someone can point me in the right direction or knows of a cool, tight routine/function that achieves what I'm looking for. Thanks in advance for any insights.
You could take an array of the wanted keys with a placeholder for the running number and build new object and push them to the result set.
var data = { vsm1: "2429", vsm2: "2488", vsm3: "1968", vsm4: "", vsm5: "", vsm6: "", vsm7: "", vsm8: "", vsm9: "", vsm10: "", color1: "5", color2: "4", color3: "4", color4: "0", color5: "0", color6: "0", color7: "0", color8: "0", color9: "0", color10: "0", p1mtime: "1549296004", p2mtime: "1549296009", p3mtime: "1549296014", p4mtime: "", p5mtime: "", p6mtime: "", p7mtime: "", p8mtime: "", p9mtime: "", p10mtime: "", inch1: "", inch2: "", inch3: "", inch4: "", inch5: "", inch6: "", inch7: "", inch8: "", inch9: "", inch10: "" },
keys = ['vsm*', 'color*', 'p*mtime', 'inch*'],
result = [],
id = 1;
while (keys[0].replace('*', id) in data) {
result.push(Object.assign(
{ id },
...keys.map(k => ({ [k.replace('*', '')]: +data[k.replace('*', id)] || 0 }))
));
id++;
}
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
With template literals
var data = { vsm1: "2429", vsm2: "2488", vsm3: "1968", vsm4: "", vsm5: "", vsm6: "", vsm7: "", vsm8: "", vsm9: "", vsm10: "", color1: "5", color2: "4", color3: "4", color4: "0", color5: "0", color6: "0", color7: "0", color8: "0", color9: "0", color10: "0", p1mtime: "1549296004", p2mtime: "1549296009", p3mtime: "1549296014", p4mtime: "", p5mtime: "", p6mtime: "", p7mtime: "", p8mtime: "", p9mtime: "", p10mtime: "", inch1: "", inch2: "", inch3: "", inch4: "", inch5: "", inch6: "", inch7: "", inch8: "", inch9: "", inch10: "" },
templates = [id => `vsm${id}`, id => `color${id}`, id => `p${id}mtime`, id => `inch${id}`],
result = [],
id = 1;
while (templates[0](id) in data) {
result.push(Object.assign(
{ id },
...templates.map(t => ({ [t('')]: +data[t(id)] || 0 }))
));
id++;
}
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Try this, with oldObject the object you want to clean:
var cleanedObject = {};
for (let [key, value] of Object.entries(oldObject)) {
let index = key.match('[0-9]+');
cleanedObject[index] = cleanedObject[index] || {};
cleanedObject[index][key.replace(index, '')] = value;
}
The result will be an object where cleanedObject['1'] = { vsm: 2429, color: 5, pmtime: 1549296004, inch: '' }, and so on.
This solution has a different flexibility than the one from Nina Sholz. Nina's allows you to match any style of number-containing key. But it also requires you to add a template in order to do so. Mine will handle any keys which contain only a single run of digits but nothing more complex. But it doesn't require you to do anything to handle such templates.
const reformat = data => Object.values(Object.keys(data)
.reduce(
(a, k, i, _, d = k.match(/\d+/)[0]) => ({
...a,
[d]: {...(a[d] || {id: Number(d)}), [k.replace(/\d+/, '')]: data[k]}
}), {})).sort((a, b) => a.id - b.id)
const data = {"vsm1":"2429","vsm2":"2488","vsm3":"1968","vsm4":"","vsm5":"","vsm6":"","vsm7":"","vsm8":"","vsm9":"","vsm10":"","color1":"5","color2":"4","color3":"4","color4":"0","color5":"0","color6":"0","color7":"0","color8":"0","color9":"0","color10":"0","p1mtime":"1549296004","p2mtime":"1549296009","p3mtime":"1549296014","p4mtime":"","p5mtime":"","p6mtime":"","p7mtime":"","p8mtime":"","p9mtime":"","p10mtime":"","inch1":"","inch2":"","inch3":"","inch4":"","inch5":"","inch6":"","inch7":"","inch8":"","inch9":"","inch10":""}
console.log(reformat(data))
I have no idea if you need either sort of flexibility, but these are interesting alternatives to one another.
I now see that my answer is basically the same as Ninas, haven't seen templating before so that was cool, but seeing as this i the first time i've tried to answer something here I'll just share it anyway.
As Ninas this can handle any length of data.
const data = {"vsm1": "2429",
"vsm2": "2488",
"vsm3": "1968",
"vsm4": "",
"color1": "5",
"color2": "4",
"color3": "4",
"color4": "0",
"p1mtime": "1549296004",
"p2mtime": "1549296009",
"p3mtime": "1549296014",
"p4mtime": "",
"inch1": "",
"inch2": "",
"inch3": "",
"inch4": "",
};
const vsmRegex = new RegExp("(vsm\\d)");
const keys = Object.keys(data);
const result = [];
let id= 1;
for(let i = 0; i < keys.length; i++) {
if(keys[i].match(vsmRegex)) {
let object = {
id: id,
vsm: Number(data[`vsm${id}`]) || 0,
color: Number(data[`color${id}`]) || 0,
pmtime: Number(data[`p${id}mtime`]) || 0,
inch: Number(data[`inch${id}`]) || 0
};
result.push(object);
id++;
} else {
break;
}
}
console.log(result);
This Object have relationship as: childOne > childTwo > childThree > childFour > childFive > childSix.
{
"parentObj": {
"childOne": [
{
"name": "A",
"id": "1"
},
{
"name": "B",
"id": "2"
}
],
"childTwo": [
{
"name": "AB",
"parent_id": "1",
"id": "11"
},
{
"name": "DE",
"parent_id": "2",
"id": "22"
}
],
"childThree": [
{
"name": "ABC",
"parent_id": "22",
"id": "111"
},
{
"name": "DEF",
"parent_id": "11",
"id": "222"
}
],
"childFour": [
{
"name": "ABCD",
"parent_id": "111",
"id": "1111"
},
{
"name": "PQRS",
"parent_id": "111",
"id": "2222"
}
],
"childFive": [
{
"name": "FGRGF",
"parent_id": "1111",
"id": "11111"
},
{
"name": "ASLNJ",
"parent_id": "1111",
"id": "22222"
},
{
"name": "ASKJA",
"parent_id": "1111",
"id": "33333"
}
],
"childSix": [
{
"name": "SDKJBS",
"parent_id": "11111",
"id": "111111"
},
{
"name": "ASKLJB",
"parent_id": "11111",
"id": "222222"
}
]
}
}
Is there any way to delete an item by ID and the objects which are associated with that particular ID should get deleted(i.e., If I do delete parentObj.childTwo[1], then all the related object beneath it should also gets deleted).
Looping manually is too bad code, and generate bugs. There must be better ways of dealing with this kind of problems like recursion, or other.
The data structure does not allow for efficient manipulation:
By nature objects have an non-ordered set of properties, so there is no guarantee that iterating the properties of parentObj will give you the order childOne, childTwo, childThree, ... In practice this order is determined by the order in which these properties were created, but there is no documented guarantee for that. So one might find children before parents and vice versa.
Although the id values within one such child array are supposed to be unique, this object structure does not guarantee that. Moreover, given a certain id value, it is not possible to find the corresponding object in constant time.
Given this structure, it seems best to first add a hash to solve the above mentioned disadvantages. An object for knowing a node's group (by id) and an object to know which is the next level's group name, can help out for that.
The above two tasks can be executed in O(n) time, where n is the number of nodes.
Here is the ES5-compatible code (since you mentioned in comments not to have ES6 support). It provides one example call where node with id "1111" is removed from your example data, and prints the resulting object.
function removeSubTree(data, id) {
var groupOf = {}, groupAfter = {}, group, parents, keep = { false: [], true: [] };
// Provide link to group per node ID
for (group in data) {
data[group].forEach(function (node) {
groupOf[node.id] = group;
});
}
// Create ordered sequence of groups, since object properties are not ordered
for (group in data) {
if (!data[group].length || !data[group][0].parent_id) continue;
groupAfter[groupOf[data[group][0].parent_id]] = group;
}
// Check if given id exists:
group = groupOf[id];
if (!group) return; // Nothing to do
// Maintain list of nodes to keep and not to keep within the group
data[group].forEach(function (node) {
keep[node.id !== id].push(node);
});
while (keep.false.length) { // While there is something to delete
data[group] = keep.true; // Delete the nodes from the group
if (!keep.true.length) delete data[group]; // Delete the group if empty
// Collect the ids of the removed nodes
parents = {};
keep.false.forEach(function (node) {
parents[node.id] = true;
});
group = groupAfter[group]; // Go to next group
if (!group) break; // No more groups
// Determine what to keep/remove in that group
keep = { false: [], true: [] };
data[group].forEach(function (node) {
keep[!parents[node.parent_id]].push(node);
});
}
}
var tree = {"parentObj": {"childOne": [{"name": "A","id": "1"},{"name": "B","id": "2"}],"childTwo": [{"name": "AB","parent_id": "1","id": "11"},{"name": "DE","parent_id": "2","id": "22"}],"childThree": [{"name": "ABC","parent_id": "22","id": "111"},{"name": "DEF","parent_id": "11","id": "222"}],"childFour": [{"name": "ABCD","parent_id": "111","id": "1111"},{"name": "PQRS","parent_id": "111","id": "2222"}],"childFive": [{"name": "FGRGF","parent_id": "1111","id": "11111"},{"name": "ASLNJ","parent_id": "1111","id": "22222"},{"name": "ASKJA","parent_id": "1111","id": "33333"}],"childSix": [{"name": "SDKJBS","parent_id": "11111","id": "111111"},{"name": "ASKLJB","parent_id": "11111","id": "222222"}]}}
removeSubTree(tree.parentObj, "1111");
console.log(tree.parentObj);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Sure, the function you use to delete an entry should FIRST recurse, which means run itself on the linked entry, unless there is none. So, in psuedocode
function del(name, index)
{
if parent[name][index] has reference
Then del(reference name, reference ID)
Now del parent[name][index]
}
No loop needed.
And since we stop if there is no reference, we do not recurse forever.
Not sure what it is you want but maybe this will work:
const someObject = {
"parentObj": {
"childOne": [
{
"name": "A",
"id": "1"
},
{
"name": "B",
"id": "2"
}
],
"childTwo": [
{
"name": "AB",
"childOne": "1",
"id": "11"
},
{
"name": "DE",
"childOne": "2",
"id": "22"
}
]
}
};
const removeByID = (key,id,parent) =>
Object.keys(parent).reduce(
(o,k)=>{
o[k]=parent[k].filter(
item=>
!(Object.keys(item).includes(key)&&item[key]===id)
);
return o;
},
{}
);
const withoutID = Object.assign(
{},
someObject,
{ parentObj : removeByID("childOne","1",someObject.parentObj) }
);
console.log(`notice that childTwo item with childOne:"1" is gone`);
console.log("without key:",JSON.stringify(withoutID,undefined,2));
const otherExample = Object.assign(
{},
someObject,
{ parentObj : removeByID("childOne","2",someObject.parentObj) }
);
console.log(`notice that childTwo item with childOne:"2" is gone`);
console.log("without key:",JSON.stringify(otherExample,undefined,2));
const both = Object.assign(
{},
someObject,
{ parentObj : removeByID("childOne","1",otherExample.parentObj) }
);
console.log(`notice that childTwo items with childOne are both gone`);
console.log("without key:",JSON.stringify(both,undefined,2));