How to filtering out the multiple nested object in Javascript object - javascript

Javascript
I have a nested array of objects, I'm trying to filter the given array of objects using a property from the third level of its array property value. For example, from the below array I like to filter the entire array using the property ListId: 10
Example
let test = {
"test":true,
"group":[
{
"name":"header",
"value":[
{
"id":"0",
"list":[
{
"ListId":10,
"name":"string1",
"state":"BY",
"techId":0
},
{
"ListId":11,
"name":"string2",
"state":"BY"
},
{
"ListId":12,
"name":"string3",
"state":"BY"
}
]
}
]
},
{
"name":"header2",
"value":[
{
"id":"01",
"list":[
{
"ListId":100,
"name":"string1",
"state":"BY",
"techId":0
},
{
"ListId":111,
"name":"string2",
"state":"BY"
},
{
"ListId":121,
"name":"string3",
"state":"BY"
}
]
}
]
}
]
}
Filtervalue with ListId = 10
Expected output :
{
"test":true,
"group":[
{
"name":"header",
"value":[
{
"id":"0",
"list":[
{
"ListId":10,
"name":"string1",
"state":"BY",
"techId":0
}
]
}
]
}
]
}
How can I use the filter method using javascript to get this expected result?

You can two it in two times :
First, filter the list arrays,
Secondly filter the groups array using the some method
let test= {
"test": true,
"group": [
{
"name": "header",
"value": [
{
"id": "0",
"list": [
{
"ListId": 10,
"name": "string1",
"state": "BY",
"techId": 0
},
{
"ListId": 11,
"name": "string2",
"state": "BY"
},
{
"ListId": 12,
"name": "string3",
"state": "BY"
}
]
}
]
},
{
"name": "header2",
"value": [
{
"id": "01",
"list": [
{
"ListId": 100,
"name": "string1",
"state": "BY",
"techId": 0
},
{
"ListId": 111,
"name": "string2",
"state": "BY"
},
{
"ListId": 121,
"name": "string3",
"state": "BY"
}
]
}
]
}
]
}
test.group.forEach(group => {
group.value.forEach(value => {
value.list = value.list.filter(list => list.ListId === 10)
})
})
test.group = test.group.filter(group => group.value.some(value => value.list.length > 0))
console.log(test)
Note : You should use plural names for you arrays, it helps understanding the data. For example lists not list for the array.

let z ={"group1": [
{
"name": "header",
"value": [
{
"id": 0,
"list": [
{
"ListId": 10,
"Name": "string1"
},
{
"ListId": 11,
"Name": "string2"
}
]
}
]
}
]}
// This function was written from understading that 'group1' is not a fixed property, but part of a dynamic list due to the number '1'
const getItemByListId = (list, listId) => {
const listKeys = Object.keys(list);
const selectedListKey = listKeys.find(key => {
const groupItems = list[key];
const selectedItem = groupItems.find(({ value: nestedItems }) => {
const selectedNestedItem = nestedItems.find(({ list }) => {
const selectedList = list.find(({ ListId }) => ListId === listId)
return selectedList;
});
return selectedNestedItem;
});
return selectedItem;
});
if (!selectedListKey) {
return null;
}
return list[selectedListKey];
};
console.log(getItemByListId(z, 10));

Related

How to Filter Nested Object Array Without affecting References in JavaScript

Just want to remove all the items other than 14 from the parentId: 1001 and add that item to another object.
I want to filter the array without affecting the source array.
var Data = [{
"id": 1001,
"text": "A",
"items": [
{ "id": 13, "text": "Thirteen" },
{ "id": 14, "text": "Fourteen" },
{ "id": 15, "text": "Fifteen", }
]
},
{
"id": 1002,
"text": "B",
"items": [
{ "id": 21, "text": "TwentyOne" },
{ "id": 22, "text": "TwentyTwo" },
{ "id": 23, "text": "TwentyThree", }
]
}
]
var childId = 14;
Data.items.filter((x) => {
return x.id != childId;
})
//this is affecting the source array (Data)
//after searching on internet found a solution
Data.items.filter((x) => {
return x.id childId;
}).map(function(x) {
return x
});
Your Data has no items property: it is an array, so you actually have Data[0].items, Data[1].items, ...
NB: it is common practice to use camelCase for such variable names, and reserve PascalCase for constructors/classes
Here is how you could do it:
const data = [{"id": 1001,"text": "A","items": [{ "id": 13, "text": "Thirteen" }, { "id": 14, "text": "Fourteen" }, { "id": 15, "text": "Fifteen", }]},{"id": 1002,"text": "B","items": [{ "id": 21, "text": "TwentyOne" }, { "id": 22, "text": "TwentyTwo" }, { "id": 23, "text": "TwentyThree", }]}]
const childId = 14;
const newData = data.map(obj => ({
...obj,
items: obj.items.filter(x => x.id != childId)
}));
console.log(newData);
As you want to filter out a few items from an array object and want to add those into another object.
You can also achieve this requirement by doing a deep copy of an original array with the help of structuredClone() API and then iterating it using Array#forEach method.
Live demo :
const data=[
{
"id":1001,
"text":"A",
"items":[
{
"id":13,
"text":"Thirteen"
},
{
"id":14,
"text":"Fourteen"
},
{
"id":15,
"text":"Fifteen",
}
]
},
{
"id":1002,
"text":"B",
"items":[
{
"id":21,
"text":"TwentyOne"
},
{
"id":22,
"text":"TwentyTwo"
},
{
"id":23,
"text":"TwentyThree",
}
]
}
];
const clone = structuredClone(data);
let remainingItems = [];
clone.forEach(obj => {
if (obj.id === 1001) {
remainingItems = obj.items.filter(({ id }) => id !== 14);
obj.items = obj.items.filter(({ id }) => id === 14);
} else {
obj.items = [...obj.items, ...remainingItems];
}
})
console.log('cloned data_____', clone);
console.log('source data_____', data);

If the 'id' key is duplicated among the objects in the array, how to delete the object [duplicate]

This question already has answers here:
How to remove all duplicates from an array of objects?
(77 answers)
Closed 4 months ago.
If the 'id' key is duplicated among the objects in the array, how to delete the object
I tried using filter, map, and set, but it doesn't work.
It's not a one-dimensional array, so I don't know how to do it.
as-is
"category": {
"key": 1,
"order": 1,
"list": [
{
"id": "12345",
...
},
{
"id": "12345",
...
},
{
"id": "67890",
...
},
]
}
to-be
"category": {
"key": 1,
"order": 1,
"list": [
{
"id": "12345",
...
},
{
"id": "67890",
...
},
]
}
We iterate over that list using reduce function, then we checked whether the key we are accessing is visited or not with keys parameter of reduce method, and if it's not visited then we just push that object to a filtered array and returning keys array to keep it updated.
const data = {
"category": {
"key": 1,
"order": 1,
"list": [{
"id": "12345"
},
{
"id": "12345"
},
{
"id": "67890"
},
]
}
}
let filtered = [];
data.category.list.reduce((keys, currentObject) => {
if (!keys.includes(currentObject.id)) { //checking if current oject id is present in keys or not
// if not present than we will just push that object in
keys.push(currentObject.id);
//getting filttered object
filtered.push(currentObject);
}
return keys; //returning keys to update it
}, [])
data.category.list = filtered; //updating list
console.log(data);
A solution based on #Nick's comment
let data ={
"category": {
"key": 1,
"order": 1,
"list": [
{
"id": "12345"
},
{
"id": "12345"
},
{
"id": "67890"
},
]
}
}
let uniq = data.category.list.filter((o,i,a) => a.findIndex(o2 => o2.id == o.id) == i)
data.category.list = uniq
console.log(data)
You can use a set to track if id
const category = [{
"category": {
"key": 1,
"order": 1,
"list": [{
"id": "12345",
},
{
"id": "12345",
},
{
"id": "67890",
},
]
}
}]
const z = category.map(elem => {
const set = new Set()
return {
...elem,
category: {
...elem.category,
list: elem.category.list.reduce((acc, curr) => {
if (!set.has(curr.id)) {
set.add(curr.id);
acc.push(curr)
}
return acc;
}, [])
}
}
});
console.log(z)

Javascript array of arrays that contains obj, take only arrays that contain an obj with a specific key

I have array of arrays that contains obj, I should only take arrays that contain an obj with a specific key.
I tried to use a double filter but it doesn't work.
Can you give me some advice?
let result = [
[
{
"id": 1
},
{
"id": 2
}
],
[
{
"id": 3
},
{
"id": 4
},
{
"id": 5,
"type": {
"id": 1555
}
}
],
[
{
"id": 6,
"type": {
"id": 5456
}
}
]
];
const c = result.filter(array => array.filter(a => a.hasOwnProperty('type') === true));
console.log(c);
Result:
[
[
{
"id": 3
},
{
"id": 4
},
{
"id": 5,
"type": {
"id": 1555
}
}
],
[
{
"id": 6,
"type": {
"id": 5456
}
}
]
]
The filter in your filter function is wrong because you don't want to return a new collection, you want to return a boolean expression. Array.some() helps and checks if any item in that subarray has this property.
let result = [
[{
"id": 1
},
{
"id": 2
}
],
[{
"id": 3
},
{
"id": 4
},
{
"id": 5,
"type": {
"id": 1555
}
}
],
[{
"id": 6,
"type": {
"id": 5456
}
}]
];
const validArrays = result.filter(subArray => subArray.some(item => item.hasOwnProperty('type')));
console.log(validArrays);
You'll have to check whether the length of the return value from the inner array is > 0. Only if the length of the return value from the inner filter is > 0 the outer filter returns true and store it into validArrays.
let result = [[{"id":1},{"id":2}],[{"id":3},{"id":4},{"id":5,"type":{"id":1555}}],[{"id":6,"type":{"id":5456}}]];
const validArrays = result.filter(subarray => subarray.filter(item => item.hasOwnProperty('type') === true).length > 0);
console.log(validArrays);

sort json nested array based on index not working as expected

I have a json array and I want to sort the array based on its index number
[
{
"name":"abc",
"index":2,
"values":[
{
"work":"three3",
"index":3
},
{
"work":"one1",
"index":1
},
{
"work":"two2",
"index":2
}
]
},
{
"name":"pqr",
"index":1,
"values":[
{
"work":"three",
"index":3
},
{
"work":"two",
"index":2
},
{
"work":"one",
"index":1
}
]
}
]
What I expect from this array is:
[
{
"filename":"pqr",
"children":[
{
"work":"one",
"index":1
},
{
"work":"two",
"index":2
},
{
"work":"three",
"index":3
}
]
},
{
"filename":"abc",
"children":[
{
"work":"one1",
"index":1
},
{
"work":"two2",
"index":2
},
{
"work":"three3",
"index":3
}
]
}
]
Tried something like below.
const filterBy = (arr, childname, filterText) =>
{
return arr.map(({filename, children}) =>
{
return {filename, children: children.map(({filename, children}) =>
{
if (filename === childname)
return {filename, children: children.filter(
x => x.filename.match(filterText)
)};
else
return {filename, children};
})};
});
}
It is a json array and what we can not be sure it will be in order so I want an array or object should be in sorted order
But how can I include that index in inner level and outer level and sort using it accordingly?
You can first sort the array based on index. This will return a sorted array now use map. Inside the callback function get the values array and again sort it.Inside the array map function return the object with required key and value
let data = [{
"name": "abc",
"index": 2,
"values": [{
"work": "three3",
"index": 3
},
{
"work": "one1",
"index": 1
},
{
"work": "two2",
"index": 2
}
]
},
{
"name": "pqr",
"index": 1,
"values": [{
"work": "three",
"index": 3
},
{
"work": "two",
"index": 2
},
{
"work": "one",
"index": 1
}
]
}
]
let newdt = data.sort(function(a, b) {
return a.index - b.index
}).map(function(item) {
let val = item.values.sort(function(a, b) {
return a.index - b.index;
})
return {
name: item.name,
children: val
}
})
console.log(newdt)
First sort the outer array, use same function to sort inner array
function compare(a, b) {
if (a.index < b.index)
return -1;
if (a.index > b.index)
return 1;
return 0;
}
var objs = [{
"name": "abc",
"index": 2,
"values": [{
"work": "three3",
"index": 3
},
{
"work": "one1",
"index": 1
},
{
"work": "two2",
"index": 2
}
]
},
{
"name": "pqr",
"index": 1,
"values": [{
"work": "three",
"index": 3
},
{
"work": "two",
"index": 2
},
{
"work": "one",
"index": 1
}
]
}
]
var result = objs.sort(compare).map(function(item) {
var children = item.values.sort(compare);
return {
filename: item.name,
children: children
}
});
console.log(result);

node js create an object in specific pattern from array of object

I'm facing some issue in for loop while creating an object from array of object.I have an array as this in node js app:
[
{
"Material": "113/133",
"Name": [
{
"name": "WELD1",
"value": 27520
},
{
"name": "WELD2",
"value": 676992
},
{
"name": "WELD3",
"value": 421
}
]
},
{
"Material": "150/300",
"Name": [
{
"name": "WELD1",
"value": 1441
},
{
"name": "WELD2",
"value": 555
},
{
"name": "WELD3",
"value": 100992
}
]
}
]
I want to return object like this which contains all the Material as array, Name and there value in array of object like this:
{
Material: ["113/133", "150/300"],
datasets: [
{
label: "WELD1",
data: [27520,1441]
},
{
label: "WELD2",
data: [676992,555]
},
{
label: "WELD3",
data: [100,20,0]
}
]
}
I want to get result using for loop.
you can use .reduce() and do something like this:
var arr = [
{
"Material": "113/133",
"Name": [
{
"name": "WELD1",
"value": 27520
},
{
"name": "WELD2",
"value": 676992
},
{
"name": "WELD3",
"value": 421
}
]
},
{
"Material": "150/300",
"Name": [
{
"name": "WELD1",
"value": 1441
},
{
"name": "WELD2",
"value": 555
},
{
"name": "WELD3",
"value": 100992
}
]
}
];
var newArr = arr.reduce((acc, ob) => {
for (var key in ob)
if(typeof acc[key] === 'object')
acc[key] = acc[key] ? acc[key].concat(ob[key]) : [ob[key]];
else
acc[key] ? acc[key].push(ob[key]) : acc[key] = [ob[key]];
return acc;
}, {});
console.log(newArr);
let array = [
{
"Material": "113/133",
"Name": [
{
"name": "WELD1",
"value": 27520
},
{
"name": "WELD2",
"value": 676992
},
{
"name": "WELD3",
"value": 421
}
]
},
{
"Material": "150/300",
"Name": [
{
"name": "WELD1",
"value": 1441
},
{
"name": "WELD2",
"value": 555
},
{
"name": "WELD3",
"value": 100992
}
]
}
]
let answer = {Material: [], datasets: []}
array.forEach(x => {
answer.Material.push(x.Material);
x.Name.forEach(na => {
let object = answer.datasets.find(obj => obj.label === na.name) || {label: "", data: []};
if(object.label === ""){
object.label = na.name;
object.data.push(na.value);
answer.datasets.push(object);
}else{
object.data.push(na.value)
}
});
});
console.log(answer);
The above is alternative solution using forEach instead of reduce
Use of Array.reduce to build your new data structure using data you have
const start = [{
"Material": "113/133",
"Name": [{
"name": "WELD1",
"value": 27520
},
{
"name": "WELD2",
"value": 676992
},
{
"name": "WELD3",
"value": 421
}
]
},
{
"Material": "150/300",
"Name": [{
"name": "WELD1",
"value": 1441
},
{
"name": "WELD2",
"value": 555
},
{
"name": "WELD3",
"value": 100992
}
]
}
];
const end = start.reduce((tmp, {
Material,
Name,
}) => {
// Handle the material
// If it do not exist in the array, push it
if (!tmp.Material.includes(Material)) {
tmp.Material.push(Material);
}
// Handle the datasets
// Look at each Name
Name.forEach(({
name,
value,
}) => {
// Can we find the label?
const labelFind = tmp.datasets.find(y => y.label === name);
// If we can't find the label, create a new dataset
if (!labelFind) {
tmp.datasets.push({
label: name,
data: [
value,
],
});
return;
}
// If we has found it push new value in the dataset
labelFind.data.push(value);
});
return tmp;
}, {
Material: [],
datasets: [],
});
console.log(end);
// This is the old fashioned way.
// Iterate over whole array,
// make a map, push value where 'name' is found in map
// later iterate over this map - dataMap - and form required datasets array.
var Material = [];
var dataMap = {};
arr.forEach(obj => {
Material.push(obj.Material);
obj.Name.forEach(item => {
if(dataMap[item.name]){
dataMap[item.name].push(item.value);
}
else {
dataMap[item.name] = [item.value];
}
});
});
var datasets = [];
Object.keys(dataMap).forEach(label => {
datasets.push({
label: label,
data: dataMap[label]
});
});
var result = {
Material: Material,
datasets: datasets
}
console.log(result);

Categories