how to extract objects from array of object based on similar id - javascript

I have created this sample code , to explain what i am tring to do .
arr = [
{ id:1 , name:'a', title: 'qmummbw' },
{ id:2 , name:'b', title: 'sdmus' },
{ id:2 , name:'', title: 'dvfv' },
{ id:3 , name:'c', title: 'dujuw' },
{ id:1 , name:'d', title: 'ccnyu' },
{ id:4 , name:'e', title: 'tjtjn' },
{ id:4 , name:'f', title: 'tryr' },
{ id:1 , name:'g', title: 'gbgfbgf' },
{ id:2 , name:'h', title: 'tgrtg' },
{ id:3 , name:'i', title: 'fdvd' },
{ id:1 , name:'j', title: 'dsnyc' },
{ id:1 , name:'k', title: 'nyuny' }
];
array = [];
allArray = [];
for (i = 0; i < arr.length; i++) {
for (j = i + 1; j < arr.length; j++) {
if (arr[i].id === arr[j].id) {
if (!array.includes(arr[i])) {
array.push(arr[i], arr[j]);
} else {
array.push(arr[j]);
}
allArray.push(array);
array = []
}
}
}
console.log(allArray);
Output i am getting is:
[[{
id: 1,
name: "a",
title: "qmummbw"
}, {
id: 1,
name: "d",
title: "ccnyu"
}], [[circular object Object], {
id: 1,
name: "g",
title: "gbgfbgf"
}], [[circular object Object], {
id: 1,
name: "j",
title: "dsnyc"
}], [[circular object Object], {
id: 1,
name: "k",
title: "nyuny"
}], [{
id: 2,
name: "b",
title: "sdmus"
}, {
id: 2,
name: "",
title: "dvfv"
}], [[circular object Object], {
id: 2,
name: "h",
title: "tgrtg"
}], [[circular object Object], [circular object Object]], [{
id: 3,
name: "c",
title: "dujuw"
}, {
id: 3,
name: "i",
title: "fdvd"
}], [[circular object Object], [circular object Object]], [[circular object Object], [circular object Object]], [[circular object Object], [circular object Object]], [{
id: 4,
name: "e",
title: "tjtjn"
}, {
id: 4,
name: "f",
title: "tryr"
}], [[circular object Object], [circular object Object]], [[circular object Object], [circular object Object]], [[circular object Object], [circular object Object]]]
My main goal is to get the array of object , each object containing the same id together and keeping in mind that the arr = [] can have n no of data.

You could group by id and take the values form the object, if necessary.
const
array = [{ id: 1 , name: 'a', title: 'qmummbw' }, { id: 2 , name: 'b', title: 'sdmus' }, { id: 2 , name: '', title: 'dvfv' }, { id: 3 , name: 'c', title: 'dujuw' }, { id: 1 , name: 'd', title: 'ccnyu' }, { id: 4 , name: 'e', title: 'tjtjn' }, { id: 4 , name: 'f', title: 'tryr' }, { id: 1 , name: 'g', title: 'gbgfbgf' }, { id: 2 , name: 'h', title: 'tgrtg' }, { id: 3 , name: 'i', title: 'fdvd' }, { id: 1 , name: 'j', title: 'dsnyc' }, { id: 1 , name: 'k', title: 'nyuny' }],
grouped = array.reduce((r, o) => ((r[o.id] = r[o.id] || []).push(o), r), {});
console.log(grouped);
.as-console-wrapper { max-height: 100% !important; top: 0; }

You can use the reduce method like this:
const filteredArray = arr.reduce((acc, el) => {
if (acc[el.id] || (acc[el.id] = [])) {
acc[el.id].push(el);
}
return acc;
}, {});

var arr = [
{ id:1 , name:'a', title: 'qmummbw' },
{ id:2 , name:'b', title: 'sdmus' },
{ id:2 , name:'', title: 'dvfv' },
{ id:3 , name:'c', title: 'dujuw' },
{ id:1 , name:'d', title: 'ccnyu' },
{ id:4 , name:'e', title: 'tjtjn' },
{ id:4 , name:'f', title: 'tryr' },
{ id:1 , name:'g', title: 'gbgfbgf' },
{ id:2 , name:'h', title: 'tgrtg' },
{ id:3 , name:'i', title: 'fdvd' },
{ id:1 , name:'j', title: 'dsnyc' },
{ id:1 , name:'k', title: 'nyuny' }
],
result = Object.values(arr.reduce(function (r, a) {
r[a.id] = r[a.id] || [];
r[a.id].push(a);
return r;
}, Object.create(null))).map(e => e);
console.log([result]);

Related

how to create from object and nested objects one array

I have this array of objects with nested objects "children".. the number of nested children arrays that can be is not defined
let a = [
{ id: 0, title: 'a', children: [ { id: 1, title: 'aa', children: [ { id: 2, title: 'aaa', children: []} ]}] },
{ id: 3, title: 'b', children: [ { id: 4, title: 'bb', children: []}] },
{ id: 5, title: 'c', children: [] },
{ id: 6, title: 'd', children: [ { id: 7, title: 'dd', children: [ { id: 8, title: 'ddd', children: []} ]}] },
]
and I need foreach them, take to the array.. with level of nested:
let b = [
{ id: 0, title: 'a', level: 0 },
{ id: 1, title: 'aa', level: 1 },
{ id: 2, title: 'aaa', level: 2 },
{ id: 3, title: 'b', level: 0 },
{ id: 4, title: 'bb', level: 1 },
{ id: 5, title: 'c', level: 0 },
{ id: 6, title: 'd', level: 0 },
{ id: 7, title: 'dd', level: 1 },
{ id: 8, title: 'ddd', level: 2 },
]
I tired recursively code, but its not working.. thank for help
Here is a recursive function called makeLevels that outputs your result.
let a = [
{ id: 0, title: 'a', children: [{ id: 1, title: 'aa', children: [{ id: 2, title: 'aaa', children: [] }] }] },
{ id: 3, title: 'b', children: [{ id: 4, title: 'bb', children: [] }] },
{ id: 5, title: 'c', children: [] },
{ id: 6, title: 'd', children: [{ id: 7, title: 'dd', children: [{ id: 8, title: 'ddd', children: [] }] }] },
];
function makeLevels(entry, result = [], level = 0) {
for (let i = 0, len = entry.length; i < len; i++) {
const item = entry[i];
result.push({ id: item.id, title: item.title, level });
if (item.children?.length) {
makeLevels(item.children, result, level + 1);
}
}
return result;
}
console.log(makeLevels(a));
Output:
[
{ "id": 0, "title": "a", "level": 0 },
{ "id": 1, "title": "aa", "level": 1 },
{ "id": 2, "title": "aaa", "level": 2 },
{ "id": 3, "title": "b", "level": 0 },
{ "id": 4, "title": "bb", "level": 1 },
{ "id": 5, "title": "c", "level": 0 },
{ "id": 6, "title": "d", "level": 0 },
{ "id": 7, "title": "dd", "level": 1 },
{ "id": 8, "title": "ddd", "level": 2 }
]
You can try this approach:
let a = [{ id: 0, title: 'a', children: [ { id: 1, title: 'aa', children: [ { id: 2, title: 'aaa', children: []} ]}] }, { id: 3, title: 'b', children: [ { id: 4, title: 'bb', children: []}] }, { id: 5, title: 'c', children: [] }, { id: 6, title: 'd', children: [ { id: 7, title: 'dd', children: [ { id: 8, title: 'ddd', children: []} ]}] },]
function flattenArray(arr, index = 0) {
return arr.reduce((acc, {children, ...rest}) => [
...acc,
{...rest, level: index},
...flattenArray(children, index+1)
],
[])
}
console.log(flattenArray(a))
To make it a little more readable, you could also do it like this.
let a = [{ id: 0, title: 'a', children: [ { id: 1, title: 'aa', children: [ { id: 2, title: 'aaa', children: []} ]}] }, { id: 3, title: 'b', children: [ { id: 4, title: 'bb', children: []}] }, { id: 5, title: 'c', children: [] }, { id: 6, title: 'd', children: [ { id: 7, title: 'dd', children: [ { id: 8, title: 'ddd', children: []} ]}] },]
function levels(obj, level = 0, arr = []) {
for (const { id, title, children } of obj) {
arr.push({ id, title, level });
if (Array.isArray(children)) levels(children, level + 1, arr);
}
return arr;
}
console.log(levels(a))

Filter Array of objects with nested array

so I am trying to set up a nested filter on an array of objects.
The thing is that the filter is applied inside the object on a key that is another array of objects.
here is the code:
const items = [
{ name: "123", id: 1, value: true, arr: [{ id: 1 }] },
{ name: "456", id: 2, value: false, arr: [{ id: 2 }] },
{ name: "456", id: 2, value: false, arr: [{ id: 3 }] },
{ name: "456", id: 2, value: false, arr: [{ id: 4 }] },
{ name: "456", id: 2, value: false, arr: [{ id: 5 }] },
{ name: "456", id: 2, value: false, arr: [{ id: 6 }] },
];
const newArray = items.filter((objects) => {
objects.arr.filter((item) => {
if (item.id === 2) {
return objects;
}
});
});
console.log(newArray);
I 'm not sure where to put the return because in this situation i just get an empty array.
You need to check the nested array contains the wanted id and return the result to the filter method.
const
items = [{ name: "123", id: 1, value: true, arr: [{ id: 1 }] }, { name: "456", id: 2, value: false, arr: [{ id: 2 }] }, { name: "456", id: 2, value: false, arr: [{ id: 3 }] }, { name: "456", id: 2, value: false, arr: [{ id: 4 }] }, { name: "456", id: 2, value: false, arr: [{ id: 5 }] }, { name: "456", id: 2, value: false, arr: [{ id: 6 }] }],
result = items.filter(({ arr }) => arr.some(({ id }) => id === 2));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Use Array#some to check if current arr has an element with id equal to 2:
const items = [ { name: "123", id: 1, value: true, arr: [{ id: 1 }] }, { name: "456", id: 2, value: false, arr: [{ id: 2 }] }, { name: "456", id: 2, value: false, arr: [{ id: 3 }] }, { name: "456", id: 2, value: false, arr: [{ id: 4 }] }, { name: "456", id: 2, value: false, arr: [{ id: 5 }] }, { name: "456", id: 2, value: false, arr: [{ id: 6 }] } ];
const newArray = items.filter(({ arr = [] }) =>
arr.some(({ id }) => id === 2)
);
console.log(newArray);
As you contains only one object in arr then you can access this object by using [0] index.
Working Demo :
const items = [
{ name: "123", id: 1, value: true, arr: [{ id: 1 }] },
{ name: "456", id: 2, value: false, arr: [{ id: 2 }] },
{ name: "456", id: 2, value: false, arr: [{ id: 3 }] },
{ name: "456", id: 2, value: false, arr: [{ id: 4 }] },
{ name: "456", id: 2, value: false, arr: [{ id: 5 }] },
{ name: "456", id: 2, value: false, arr: [{ id: 6 }] },
];
const newArray = items.filter((obj) => {
if (obj.arr[0].id === 2) {
return obj;
}
});
console.log(newArray);
I answered you as per the issue you are facing but if you have multiple objects in your arr then you can go ahead with Array.some() method as suggested by other answers.

How to filter array key by another array number key

I have 2 array, first array structure is:
items: [
{
name: "a",
items: [
{ name: "jack" },
{ name: "jose" },
]
},
{
name: "b",
items: [
{ name: "lara" },
{ name: "jo" },
]
},
{
name: "c",
items: [
{ name: "andy" },
{ name: "hary" },
]
}
]
and the second array:
number: [
0: [0, 1],
1: [1],
2: [0]
]
How to filter "items" by "number" and How can such an output be obtained? (the best solution)
{["jack", "jole"],["jo"],["andy"]}
A few maps would do it:
the output you wish is not valid JS so I made a nested array
const arr1 = [{ name: "a", items: [{ name: "jack" }, { name: "jose" }, ] }, { name: "b", items: [{ name: "lara" }, { name: "jo" }, ] }, { name: "c", items: [{ name: "andy" }, { name: "hary" }, ] } ], numbers = [ [0, 1], [1], [0] ];
const res = numbers
.map((arr, i) => arr
.map(key => arr1[i].items[key].name)
)
console.log(res)
If your number variable has to be an Object.
let items = [
{
name: "a",
items: [{ name: "jack" }, { name: "jose" }]
},
{
name: "b",
items: [{ name: "lara" }, { name: "jo" }]
},
{
name: "c",
items: [{ name: "andy" }, { name: "hary" }]
}
];
let number = {
0: [0, 1],
1: [1],
2: [0]
};
let result = []
for (const [key, value] of Object.entries(number)){
let names = []
value.forEach(value => {
names.push(items[key].items[value].name)
})
result.push(names)
}
console.log(result)

How to filter nested arrays by searching

I have an array of objects that I want to filter by comparing a nested property to a search term.
For example:
let array = [
{
category: 15,
label: "Components",
value: "a614741f-7d4b-4b33-91b7-89a0ef96a099",
children: [
{
category: 1,
label: "Carousel1",
diId: 55946,
// as you can see there are many children nested array of object
children: [{ label: "nodatafoundmessage", value: "47d18fb2-3e63-4542-ad0e-e5e09acb5016", children: [] }],
value: "be5e027b-9163-4cfb-8816-0c8e3b816086"
},
{
category: 2,
label: "Checkbox1",
diId: 193909,
children: [{ label: "datafound", value: "47d18sb2-3e63-4542-ad0e-e5e09acb5016", children: [] }],
value: "045e8786-2165-4e1e-a839-99b1b0ceef57"
}
]
},
{
value: "4be22726-850c-4905-ab3b-039fcf607d55",
label: "Default",
children: [
{
category: 5,
defaultValueType: 1,
label: "Empty",
toType: "String",
value: "ebedb43f-4c53-491f-8954-d030321845cd"
},
{
category: 5,
defaultValueType: 2,
label: "Space",
toType: "String",
value: "2d0e1429-572b-4f21-9f83-3340bafff95a"
},
{
category: 5,
defaultValueType: 8,
label: "Current Username",
toType: "String",
value: "25f6b40a-33c7-4f17-b29d-99e8d1e4e33c"
},
{
category: 5,
defaultValueType: 9,
label: "Current Location",
toType: "Location",
value: "ed59da2f-318d-4599-9085-4d9d769a27d7"
}
]
},
{
category: 4,
label: "Fixed Value",
isFixed: true,
value: "28e90e3e-a20b-4499-9593-061a7d1e7bd6"
// as you can see there is no children in this object
}
]};
What I'm trying to achieve is if I search for 'nodata' for example my result should be
let array = [
{
category: 15,
label: "Components",
value: "a614741f-7d4b-4b33-91b7-89a0ef96a099",
children: [
{
category: 1,
label: "Carousel1",
diId: 55946,
// as you can see there are many children nested array of object
children: [{ label: "nodatafoundmessage", value: "47d18fb2-3e63-4542-ad0e-e5e09acb5016", children: [] }],
value: "be5e027b-9163-4cfb-8816-0c8e3b816086"
}
]
}
];
Another option if I search for 'spa' my result should be
let array = [
{
value: "4be22726-850c-4905-ab3b-039fcf607d55",
label: "Default",
children: [
{
category: 5,
defaultValueType: 2,
label: "Space",
toType: "String",
value: "2d0e1429-572b-4f21-9f83-3340bafff95a"
}
]
}
];
I have been super confused and I decided to get some help. Thank you for your helps guys!
The following function should do the trick for you:
function searchData(dataArray, searchTerm) {
return dataArray.flatMap(obj => {
const objHasSearchTerm = Object.entries(obj)
.some(([key, value]) => key !== 'children' && String(value).toLowerCase().includes(searchTerm.toLowerCase()));
if (objHasSearchTerm && !obj.children) return [obj];
const matchedChildren = searchData(obj.children ?? [], searchTerm);
return objHasSearchTerm || matchedChildren.length > 0
? [{
...obj,
children: matchedChildren,
}]
: [];
})
}
It recursively goes through the data array, looks for any entries that have the specified search term, and if so, places it into the newly constructed object. It will preserve the nested shape of the object, which may or may not be what is needed. Feel free to tweak the algorithm to your own needs.
let allData = [
{
category: 15,
label: "Components",
value: "a614741f-7d4b-4b33-91b7-89a0ef96a099",
children: [
{
category: 1,
label: "Carousel1",
diId: 55946,
// as you can see there are many children nested array of object
children: [{ label: "nodatafoundmessage", value: "47d18fb2-3e63-4542-ad0e-e5e09acb5016", children: [] }],
value: "be5e027b-9163-4cfb-8816-0c8e3b816086"
},
{
category: 2,
label: "Checkbox1",
diId: 193909,
children: [{ label: "datafound", value: "47d18sb2-3e63-4542-ad0e-e5e09acb5016", children: [] }],
value: "045e8786-2165-4e1e-a839-99b1b0ceef57"
}
]
},
{
value: "4be22726-850c-4905-ab3b-039fcf607d55",
label: "Default",
children: [
{
category: 5,
defaultValueType: 1,
label: "Empty",
toType: "String",
value: "ebedb43f-4c53-491f-8954-d030321845cd"
},
{
category: 5,
defaultValueType: 2,
label: "Space",
toType: "String",
value: "2d0e1429-572b-4f21-9f83-3340bafff95a"
},
{
category: 5,
defaultValueType: 8,
label: "Current Username",
toType: "String",
value: "25f6b40a-33c7-4f17-b29d-99e8d1e4e33c"
},
{
category: 5,
defaultValueType: 9,
label: "Current Location",
toType: "Location",
value: "ed59da2f-318d-4599-9085-4d9d769a27d7"
}
]
},
{
category: 4,
label: "Fixed Value",
isFixed: true,
value: "28e90e3e-a20b-4499-9593-061a7d1e7bd6"
// as you can see there is no children in this object
}
];
function searchData(dataArray, searchTerm) {
return dataArray.flatMap(obj => {
const objHasSearchTerm = Object.entries(obj)
.some(([key, value]) => key !== 'children' && String(value).toLowerCase().includes(searchTerm.toLowerCase()));
if (objHasSearchTerm && !obj.children) return [obj];
const matchedChildren = searchData(obj.children ?? [], searchTerm);
return objHasSearchTerm || matchedChildren.length > 0
? [{
...obj,
children: matchedChildren,
}]
: [];
})
}
console.log('----- Search: nodata')
console.log(JSON.stringify(searchData(allData, 'nodata'), null, 2))
console.log('----- Search: spa')
console.log(JSON.stringify(searchData(allData, 'spa'), null, 2))

Filter array in array and get only the filtered items

I have the following array named filters and try to filter it by selected items.
At the end I want to have all filters where a selected item is, but only with the selected items
let filters = [
{
id: 0,
name: 'property',
items: [
{
id: 0,
name: 'x',
isSelected: false
},
{
id: 1,
name: 'y',
isSelected: true
}
]
},
{
id: 1,
name: 'property2',
items: [
{
id: 0,
name: 'x',
isSelected: true
},
{
id: 1,
name: 'y',
isSelected: false
}
]
}
]
I want to get the following array at the end:
let filteredFilters = [
{
id: 0,
name: 'property',
items: [
{
id: 1,
name: 'y',
isSelected: true
}
]
},
{
id: 1,
name: 'property2',
items: [
{
id: 0,
name: 'x',
isSelected: true
}
]
}
]
I tried the following code, but it does not work.
let filteredFilters = filters.filter(filter => {
return filter.items.filter(item => {
return item.isSelected === true;
})
})
You need map + filter since you're dealing with a nested array:
let filters = [
{
id: 0,
name: 'property',
items: [
{
id: 0,
name: 'x',
isSelected: false
},
{
id: 1,
name: 'y',
isSelected: true
}
]
},
{
id: 1,
name: 'property2',
items: [
{
id: 0,
name: 'x',
isSelected: true
},
{
id: 1,
name: 'y',
isSelected: false
}
]
}
]
let filteredFilters =
filters.map(
({items, ...rest}) => ({...rest, items: items.filter(item => item.isSelected)})
)
.filter(x => x.items.length > 0);
console.log(filteredFilters);

Categories