Remove data from my nested array of objects by matching values. In my case I want to strip out the objects that are NOT active. So every object that contains active 0 needs to be removed.
[
{
"id" : 1,
"title" : 'list of...',
"goals": [
{
"id": 1569,
"active": 0
},
{
"id": 1570,
"active": 1
},
{
"id": 1571,
"active": 0
}
],
},
{
"id" : 2,
"title" : 'more goals',
"goals": [
{
"id": 1069,
"active": 0
},
{
"id": 1070,
"active": 1
},
],
},
]
The following will return the array in an unchanged status
public stripGoalsByInactiveGoals(clusters) {
return clusters.filter(cluster =>
cluster.goals.filter(goal => goal.active === 1)
);
}
array.filter wait a boolean to know if it has to filter data or not
in your case you have an array of array, you want to filter "sub" array by active goal
if you want to keep only active goals change your first filter by map to return a modify value of your array filtered by a condition
function stripGoalsByInactiveGoals(clusters) {
return clusters.map(cluster => {
return {
goals: cluster.goals.filter(goal => goal.active)
};
});
}
var data = [{
"goals": [{
"id": 1569,
"active": 0
},
{
"id": 1570,
"active": 1
},
{
"id": 1571,
"active": 0
}
],
},
{
"goals": [{
"id": 1069,
"active": 0
},
{
"id": 1070,
"active": 1
},
],
},
];
function stripGoalsByInactiveGoals(clusters) {
return clusters.map(cluster => {
return {
goals: cluster.goals.filter(goal => goal.active)
};
});
}
console.log(stripGoalsByInactiveGoals(data));
You can create another array (for the case when you need the input unchanged as well) and loop the input, appending each member objects' filtered goals array. You could also avoid appending the item if goals is empty after the filter, but this example doesn't do this, because it was not specified as a requirement.
let input = [
{
"goals": [
{
"id": 1569,
"active": 0
},
{
"id": 1570,
"active": 1
},
{
"id": 1571,
"active": 0
}
],
},
{
"goals": [
{
"id": 1069,
"active": 0
},
{
"id": 1070,
"active": 1
},
],
},
]
let output = [];
for (let item of input) {
output.push({goals: item.goals.filter(element => (element.active))})
}
console.log(output);
You can follow this for a dynamic approach:
stripGoalsByInactiveGoals(clusters) {
var res = [];
this.data.forEach((item) => {
let itemObj = {};
Object.keys(item).forEach((key) => {
itemObj[key] = item[key].filter(x => x.active != 0);
res.push(itemObj);
});
});
return res;
}
Stackbiltz Demo
Related
I have a list of elements like the following data
[
{
"title": "First",
"catalogCategories": [ "sport", "economy" ]
},
{
"title": "Second",
"catalogCategories": [ "politics", "tourism" ]
},
{
"title": "Third",
"catalogCategories": [ "sport", "universe" ]
},
{
"title": "Fourth",
"catalogCategories": [ "economy", "politics" ]
}
]
I am checking for each element of the list if the catalogCategories array exists and if it does i push in a catalogData array the category of any element only once, because it happens that the category for any element can be the same, i am filtering in the catalogData array all the categories of the elements in catalogCategories
This is the following code
let categoryData = [];
let isCategory = false
for (let product of list) {
if (product.catalogCategories[0].length > 0) {
isCategory = true
let isFound = false
for (let i = 0; i < categoryData.length; i++) {
if (categoryData[i].value === product.catalogCategories[0] ||
categoryData[i].value === product.catalogCategories[1] ) {
isFound = true;
}
}
if (!isFound) {
categoryData.push({"name": "catalogCategories", "label": product.catalogCategories[0], "selected": false, "value": product.catalogCategories[0]})
}
}
My problem is here
if (!isFound) {
categoryData.push({"name": "catalogCategories", "label": product.catalogCategories[0], "selected": false, "value": product.catalogCategories[0]})
}
As you can see i always only push the first element of the catalogCategories after all these checks, how can i write down that dynamically i can push the first and / or the second ?
"value": product.catalogCategories[0]
"label": product.catalogCategories[0]
You need first check for the entire catalogCategories not only the first element product.catalogCategories[0] by using a map and use new Map to keep track of not duplicate categories.
const list = [
{
"title": "First",
"catalogCategories": [ "sport", "economy" ]
},
{
"title": "Second",
"catalogCategories": [ "politics", "tourism" ]
},
{
"title": "Third",
"catalogCategories": [ "sport", "universe" ]
},
{
"title": "Fourth",
"catalogCategories": [ "economy", "politics" ]
}
]
let categoryDataMap = new Map();
for (let product of list) {
if (product.catalogCategories.length > 0) {
product.catalogCategories.map(catalog=>{
if(!categoryDataMap.has(catalog)){
categoryDataMap.set(catalog,{"name": "catalogCategories", "label": catalog, "selected": false, "value": catalog})
}
})
}
}
const categoryData = Array.from(categoryDataMap.values())
console.log(categoryData)
{
"arr1":[
{
"name":"something1",
"id":"233111f4-9126-490d-a78b-1724009fa484"
},
{
"name":"something2",
"id":"50584c03-ac71-4225-9c6a-d12bcc542951"
},
{
"name":"Unique",
"id":"43cf14ee58ea4d8da43e9a2f208d215c"
},
{
"name":"something4",
"id":"ce0374ba-6d9b-4ff5-98b1-1191d1d2a9a7"
},
{
"name":"something5",
"id":"ef825dc3-003c-4740-955a-bb437cfb4199"
}
],
"arr2":
[
{
"name":"Unique",
"id":"43cf14ee58ea4d8da43e9a2f208d215c"}
]
}
This is list of arrays with keys and values as array, I want to return all the keys based on a particular value;
For Eg:
I want to return the parent keys which are [arr1,arr2], reason being both the arrays contain a value Unique, So I want to return the parent key of both the values, which is arr1 and arr2 respectively.
Note: The list can have n numbers of arrays.
Any help would be appreciated. Thanks in advance.
The simplest way to go about this is:
Loop through the keys in your object
Check if the array contains any objects with the name "Unique"
If so, add the objects key to an array
const obj = {
"arr1": [{ "name": "something1", "id": "233111f4-9126-490d-a78b-1724009fa484" }, { "name": "something2", "id": "50584c03-ac71-4225-9c6a-d12bcc542951" }, { "name": "Unique", "id": "43cf14ee58ea4d8da43e9a2f208d215c" }, { "name": "something4", "id": "ce0374ba-6d9b-4ff5-98b1-1191d1d2a9a7" }, { "name": "something5", "id": "ef825dc3-003c-4740-955a-bb437cfb4199" }],
"arr2": [{ "name": "Unique", "id": "43cf14ee58ea4d8da43e9a2f208d215c" }],
"arr3": [{ "name": "No unique here","id": "Example" }]
}
// Create our array that will contain the keys
const keys = []
// Loop through each key in the object
for (const prop in obj) {
// Use .some to see if any of the objects in this array have the selected name
const containsUnique = obj[prop].some(o => o.name === 'Unique')
if (containsUnique) {
// Add the current key to the array
keys.push(prop)
}
}
// Use the array of keys which contain an object named "Unique"
console.log(keys)
This is a more generic approach:
const getKeysByValue = (data, value) => {
const dataKeys = Object.keys(data);
const valueKey = Object.keys(value);
return dataKeys.filter(currKey => {
for(let element of data[currKey])
if(element[valueKey] === value[valueKey])
return true;
});
}
const data = {
"arr1":[
{
"name":"something1",
"shape": "Trapezium",
"id":"233111f4-9126-490d-a78b-1724009fa484"
},
{
"name":"something2",
"shape": "Octagon",
"id":"50584c03-ac71-4225-9c6a-d12bcc542951"
},
{
"name":"Unique",
"shape": "Square",
"id":"43cf14ee58ea4d8da43e9a2f208d215c"
},
{
"name":"something4",
"shape": "Triangle",
"id":"ce0374ba-6d9b-4ff5-98b1-1191d1d2a9a7"
},
{
"name":"something5",
"shape": "Circle",
"id":"ef825dc3-003c-4740-955a-bb437cfb4199"
}
],
"arr2":
[
{
"name":"Unique",
"shape": "Triangle",
"id":"43cf14ee58ea4d8da43e9a2f208d215c"
}
],
"arr3":
[
{
"name":"Not-Unique",
"shape": "Circle",
"id":"8hcf14ee58ea25g343e9a2f208df215c"
}
]
}
console.log(getKeysByValue(data, {"name": "something2"})); // ["arr1"]
console.log(getKeysByValue(data, {"name": "Unique"})); // ["arr1", "arr2"]
console.log(getKeysByValue(data, {"shape": "Circle"})); // ["arr1", "arr3"]
console.log(getKeysByValue(data, {"shape": "Square"})); // ["arr1"]
The function receives two parameters, data and value. value is expected to be in the format of the value you are looking to filter with. In your example you wanted it to be "Unique" and in each object in the array it was presented like "name": "Unique" so we will send it as an object, {"name": "Unique"}.
In this way you can have different value to filter with. In the example above I added a shape key and value to each element, we can filter by this value too as shown in the example above.
you can do like this :
const obj = {
"arr1": [{ "name": "something1", "id": "233111f4-9126-490d-a78b-1724009fa484" }, { "name": "something2", "id": "50584c03-ac71-4225-9c6a-d12bcc542951" }, { "name": "Unique", "id": "43cf14ee58ea4d8da43e9a2f208d215c" }, { "name": "something4", "id": "ce0374ba-6d9b-4ff5-98b1-1191d1d2a9a7" }, { "name": "something5", "id": "ef825dc3-003c-4740-955a-bb437cfb4199" }],
"arr2": [{ "name": "Unique", "id": "43cf14ee58ea4d8da43e9a2f208d215c" }],
"arr3": [{ "name": "No unique here","id": "Example" }]
}
arr=[]
//loop over dict with pair keys and value
for (const [key, value] of Object.entries(obj)) {
//get the list of name from dict and check it if it contains Unique string
value.map(e=>e.name).includes("Unique") ? arr.push(key) : false
}
console.log(arr)
You can use array some method
const data = {
"arr1": [{
"name": "something1",
"id": "233111f4-9126-490d-a78b-1724009fa484"
},
{
"name": "something2",
"id": "50584c03-ac71-4225-9c6a-d12bcc542951"
},
{
"name": "Unique",
"id": "43cf14ee58ea4d8da43e9a2f208d215c"
},
{
"name": "something4",
"id": "ce0374ba-6d9b-4ff5-98b1-1191d1d2a9a7"
},
{
"name": "something5",
"id": "ef825dc3-003c-4740-955a-bb437cfb4199"
}
],
"arr2": [{
"name": "Unique",
"id": "43cf14ee58ea4d8da43e9a2f208d215c"
}]
}
var obj = [],
keys;
for (keys in data) {
data[keys].some(a => "Unique" === a.name) && obj.push(keys);
}
console.log(obj);
An alternative way that i could think of is using Regexp
var obj = {
"arr1":[
{
"name":"something1",
"id":"233111f4-9126-490d-a78b-1724009fa484"
},
{
"name":"something2",
"id":"50584c03-ac71-4225-9c6a-d12bcc542951"
},
{
"name":"Unique",
"id":"43cf14ee58ea4d8da43e9a2f208d215c"
},
{
"name":"something4",
"id":"ce0374ba-6d9b-4ff5-98b1-1191d1d2a9a7"
},
{
"name":"something5",
"id":"ef825dc3-003c-4740-955a-bb437cfb4199"
}
],
"arr2":
[
{
"name":"Unique",
"id":"43cf14ee58ea4d8da43e9a2f208d215c"}
]
}
let str = JSON.stringify(obj);
let match = str.matchAll(/\"([\w\d]+)\":\[(?:{[\s\S]+},)*{\"name\":\"Unique\"/g);
let parent = [];
for(let m of match){
parent.push(m[1]);
}
I have a json below like this
[
{
"monthlyData": [
{
"dateYear": "2020-07",
"data": [
{
"id": "45bf4792-c5a5-44ed-b7e8-57557c4f30ee",
"date": "2020-07-13T00:00:00.000Z",
"transactionId": "160",
"amount": 70,
"active": 1,
"createdAt": "2020-07-14T02:55:43.988Z",
"updatedAt": "2020-08-14T02:55:43.988Z",
"version": 1
}
]
}
],
"hashId": "4"
},
{
"monthlyData": [
{
"dateYear": "2020-08",
"data": [
{
"id": "38fe3c68-e6aa-4c57-b4d7-dc6c4f597269",
"date": "2020-08-13T00:00:00.000Z",
"transactionId": "146",
"active": 1,
"createdAt": "2020-08-14T02:55:43.988Z",
"updatedAt": "2020-08-14T02:55:43.988Z",
"version": 1
}
]
}
],
"hashId": "5"
}
]
I have an array with list of month-year as
let datesArr = ['2020-08','2020-09','2020-10','2020-11','2020-07']
Now I want to pick a date from datesArr one by one and find if the date matches with dateYear column in whole JSON array. A copy of JSON array should be created for those dates are matched. I want to keep only those object whose dates are getting matched.
You can use array.filter
let originalArray = [
{
"monthlyData": [
{
"dateYear": "2020-07",
"data": [
{
"id": "45bf4792-c5a5-44ed-b7e8-57557c4f30ee",
"date": "2020-07-13T00:00:00.000Z",
"transactionId": "160",
"amount": 70,
"active": 1,
"createdAt": "2020-07-14T02:55:43.988Z",
"updatedAt": "2020-08-14T02:55:43.988Z",
"version": 1
}
]
}
],
"hashId": "4"
},
{
"monthlyData": [
{
"dateYear": "2020-08",
"data": [
{
"id": "38fe3c68-e6aa-4c57-b4d7-dc6c4f597269",
"date": "2020-08-13T00:00:00.000Z",
"transactionId": "146",
"active": 1,
"createdAt": "2020-08-14T02:55:43.988Z",
"updatedAt": "2020-08-14T02:55:43.988Z",
"version": 1
}
]
}
],
"hashId": "5"
}
];
let datesArr = ['2020-08','2020-09','2020-10','2020-11'];
let filtered = originalArray.filter(value => {
value.monthlyData = value.monthlyData.filter(md => {
return datesArr.includes(md.dateYear);
})
return value.monthlyData.length > 0;
})
console.log(JSON.stringify(filtered))
This example will print this below (if that is what you want):
[
{
"monthlyData": [
{
"dateYear": "2020-08",
"data": [
{
"id": "38fe3c68-e6aa-4c57-b4d7-dc6c4f597269",
"date": "2020-08-13T00:00:00.000Z",
"transactionId": "146",
"active": 1,
"createdAt": "2020-08-14T02:55:43.988Z",
"updatedAt": "2020-08-14T02:55:43.988Z",
"version": 1
}
]
}
],
"hashId": "5"
}
]
Edit for date object comparison
if datesArr is like
let datesArr = [new Date('2020-08'),new Date('2020-09')];
You can use array.some inside second filter
let filtered = originalArray.filter(value => {
value.monthlyData = value.monthlyData.filter(md => {
return datesArr.some(value1 => value1.getTime() === new Date(md.dateYear).getTime());
})
return value.monthlyData.length > 0;
})
And of course if original array has also Date object, you can discard
new Date(md.dateYear).getTime() use md.dateYear.getTime() instead
Edit for your comment:
I need to add those dates into monthData who has not matched with
datesArray with data as empty. what should i do.
You can use below code for that
let newArr = []
datesArr.forEach(date => {
let element = originalArray.find(value => {
value.monthlyData = value.monthlyData.filter(md => {
return date === md.dateYear;
})
return value.monthlyData.length > 0;
})
if (!element){
element = {
"monthlyData": [
{
"dateYear": date,
"data": []
}
],
"hashId": "something?"
}
}else {
// make a clone
element = JSON.parse(JSON.stringify(element))
}
newArr.push(element);
})
You can do it efficiently with Javascript's forEach
The code below extracts the information you require.
const bigTable = [{
"monthlyData": [{
"dateYear": "2020-07",
"data": [{
"id": "45bf4792-c5a5-44ed-b7e8-57557c4f30ee",
"date": "2020-07-13T00:00:00.000Z",
"transactionId": "160",
"amount": 70,
"active": 1,
"createdAt": "2020-07-14T02:55:43.988Z",
"updatedAt": "2020-08-14T02:55:43.988Z",
"version": 1
}]
}],
"hashId": "4"
},
{
"monthlyData": [{
"dateYear": "2020-08",
"data": [{
"id": "38fe3c68-e6aa-4c57-b4d7-dc6c4f597269",
"date": "2020-08-13T00:00:00.000Z",
"transactionId": "146",
"active": 1,
"createdAt": "2020-08-14T02:55:43.988Z",
"updatedAt": "2020-08-14T02:55:43.988Z",
"version": 1
}]
}],
"hashId": "5"
}
]
const datesArr = ['2020-08', '2020-09', '2020-10', '2020-11', '2020-07']
console.log("Version 1: a separate object for each dateYear")
datesArr.forEach(dateYear => {
console.log(dateYear+":-------------------");
bigTable.forEach(monthlyArray => {
monthlyArray.monthlyData.forEach(monthData => {
if (dateYear === monthData.dateYear) {
console.log(monthData)
}
})
})
})
console.log("Version 2: a single array with an element for each element of datesArr")
const output = datesArr.map(dateYear => bigTable.filter(monthlyObject =>
monthlyObject.monthlyData[0].dateYear=== dateYear
)
)
console.log(output)
Depending on exactly how you want it to compile the result, which is not unambiguous from your question, you should be able to adjust it to your needs.
Without an example of the output that you want, all we can do is guess what you mean.
From API I get such a json:
{
"purposes": [
{
"id": 1,
"code": "for-calls"
},
{
"id": 2,
"code": "task-management"
},
{
"id": 3,
"code": "messenger"
}
],
"availabilities": [
{
"id": 1,
"code": "free"
},
{
"id": 2,
"code": "free-basic-plan"
},
{
"id": 3,
"code": "trial-version"
}
],
"ecosystems": [
{
"id": 1,
"code": "browse-widget"
},
{
"id": 2,
"code": "web-app"
},
{
"id": 3,
"code": "installation-on-your-server"
}
]
}
How do I iterate over this json to get a new array containing the field values 'code' from each element. As a result, there should be /catalog/filter/value_of_code in each element of the array.
const obj = {
"purposes": [
{
"id": 1,
"code": "for-calls"
},
{
"id": 2,
"code": "task-management"
},
{
"id": 3,
"code": "messenger"
}
],
"availabilities": [
{
"id": 1,
"code": "free"
},
{
"id": 2,
"code": "free-basic-plan"
},
{
"id": 3,
"code": "trial-version"
}
],
"ecosystems": [
{
"id": 1,
"code": "browse-widget"
},
{
"id": 2,
"code": "web-app"
},
{
"id": 3,
"code": "installation-on-your-server"
}
]
}
const arr = Object.values(obj).reduce((acc, e) => [...acc, ...e.map(o => `/catalog/filter/${o.code}`)] ,[]);
console.log( arr );
Lets say you are receiving this JSON object in serverResp object.
Now lets check if any catalogs are present in the object.
if(Object.keys(serverResp).length)
Next we shall iterate over the catalogs
Object.keys(serverResp).forEach((cat) => )
Each cat represents a catalog. Next we shall fetch array against each key inside our forloop
const catItems = serverResp[cat];
catItems will contain all the items of a particular catalog. Now lets iterate over each catItems to get the "code" value
catItems.forEach(item => console.log(item.code));
Final piece of code will look like below-
const outputArray = [];
if(Object.keys(serverResp).length) {
Object.keys(serverResp).forEach((cat)=> {
const catItems = serverResp[cat];
catItems.forEach(item =>
outputArray.push(`/catalog/filter${item.code}`));
});
}
console.log(outputArray);
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.