Group array nested value with reduce - javascript

I need to group the array with a nested value type.Id. How to change the current groupby function to achieve this.
Current function will group using the productName or Price. Need to group using a nested value type.id
Any help would be greatly appreciated!
Group by function
static groupBy<T>(data: T[], key: string): T[] {
return <T[]>data.reduce((a, b) => {
(a[b[key]] = a[b[key]] || []).push(x);
return <T[]>a;
}, {});
}
sample value:
var sales = [
{
"productName": "AAA",
"type": {
"id": 1,
"name": "Soap"
},
"price": 90
},
{
"productName": "BBB",
"type": {
"id": 1,
"name": "Soap"
},
"price": 85
},
{
"productName": "CCC",
"type": {
"id": 1,
"name": "Soap"
},
"price": 55
},
{
"productName": "DDD",
"type": {
"id": 2,
"name": "shampoo"
},
"price": 2
},
{
"productName": "EEE",
"type": {
"id": 2,
"name": "shampoo"
},
"price": 5
}
]
Expected Result:
{1},
[
{
"productName": "AAA",
"type": {
"id": 1,
"name": "Soap"
},
"price": 90
},
{
"productName": "BBB",
"type": {
"id": 1,
"name": "Soap"
},
"price": 85
},
{
"productName": "CCC",
"type": {
"id": 1,
"name": "Soap"
},
"price": 55
}],
{2},[
{
"productName": "DDD",
"type": {
"id": 2,
"name": "shampoo"
},
"price": 2
},
{
"productName": "EEE",
"type": {
"id": 2,
"name": "shampoo"
},
"price": 5
}
]

Add an accessor function to use properties at any depth,
function groupBy<T>(data: T[], key: string): T[] {
const path: string[] = key.split('.');
const accessor = (obj: T) => path.reduce((x,y) => x[y], obj)
return <T[]>data.reduce((a, b) => {
const value = accessor(b).toString();
(a[value] = a[value] || []).push(b);
return <T[]>a;
}, {});
}
console.log(groupBy(sales, 'type.id'))
Runnable JS version
const sales = [
{
"productName": "AAA",
"type": {
"id": 1,
"name": "Soap"
},
"price": 90
},
{
"productName": "BBB",
"type": {
"id": 1,
"name": "Soap"
},
"price": 85
},
{
"productName": "CCC",
"type": {
"id": 1,
"name": "Soap"
},
"price": 55
},
{
"productName": "DDD",
"type": {
"id": 2,
"name": "shampoo"
},
"price": 2
},
{
"productName": "EEE",
"type": {
"id": 2,
"name": "shampoo"
},
"price": 5
}
]
function groupBy(data, key) {
const path = key.split('.');
const accessor = (obj) => {
return path.reduce((x,y) => {
return x[y]
}, obj).toString();
}
return data.reduce((a, b) => {
const prop = accessor(b);
(a[prop] = a[prop] || []).push(b);
//a[prop] = a[prop] || [];
//a[prop].push(b);
return a;
}, {});
}
console.log(groupBy(sales, 'type.id'))

Related

Parse Nested Level Json In javascript

Sample Input:
[
{
"id": "p1",
"top": 130,
"left": 298,
"Key": "test1",
"Next": "special"
},
{
"id": "p2",
"Key": "special",
"specialkey": [
{"key": "1", "value": "p3"},
{"key": "0", "value": "p4"},
{"key": "2", "value": "p5"}
],
"Next": "",
"RepeatText": "p8",
"RepeatTextNew": "p9",
},
{
"id": "p3",
"user": "aa",
"Key": "test3",
"Text": "hi"
},
{
"id": "p4",
"Key": "special",
"specialkey": [
{"key": "1", "value": "p6"},
{"key": "0", "value": "p7"}
]
},
{
"id": "p5",
"user": "aa",
"Key": "test5",
"Text": "hi"
},
{
"id": "p6",
"user": "aa",
"Key": "test6",
"Text": "hi"
},
{
"id": "p7",
"user": "aa",
"Key": "test7",
"Text": "hi"
},
{
"id": "p8",
"user": "aa",
"Key": "test8",
"Text": "hi"
},
{
"id": "p9",
"user": "aa",
"Key": "test9",
"Text": "hi"
}
]
Sample Output:
{
"test1": {
"id": "p1",
"top": 130,
"left": 298,
"Key": "test1",
"Next": {
"special": {
"id": "p2",
"Key": "special",
"Next": "",
"RepeatText": {
"p8": {
"id": "p8",
"user": "aa",
"Key": "test8",
"Text": "hi"
}
},
"RepeatTextNew": {
"p9": {
"id": "p9",
"user": "aa",
"Key": "test9",
"Text": "hi"
}
},
"specialkey": [
{
"key": "1",
"value": {
"id": "p3",
"user": "aa",
"Key": "test3",
"Text": "hi"
}
},
{
"key": "0",
"value": {
"id": "p4",
"Key": "special",
"specialkey": [
{
"key": "1",
"value": {
"id": "p6",
"user": "aa",
"Key": "test6",
"Text": "hi"
}
},
{
"key": "0",
"value": {
"id": "p7",
"user": "aa",
"Key": "test7",
"Text": "hi"
}
}
]
}
},
{
"key": "2",
"value": {
"id": "p5",
"user": "aa",
"Key": "test5",
"Text": "hi"
}
}
]
}
}
}
}
When the key is equal to special it can have a nested structure and for either we just need to match with the next key
With the below code, I am not able to achieve the expected output.
const processObject = ({ Next, ...rest }) => {
const result = { ...rest };
if (formatData.find((y) => y.Key == 'special')) {
const nextObject = formatData.find((y) => y.Key == 'special')
if (nextObject.specialkey) {
for (let i = 0; i < nextObject.specialkey.length; i++) {
let currentObject = formatData.find((y) => y.id === nextObject.specialkey[i].value)
nextObject.specialkey[i].value = currentObject
}
result.Next = {
[nextObject.Key]: processObject(nextObject),
};
}
}
if (Next) {
const nextObject = formatData.find((y) => y.id === Next);
result.Next = {
[nextObject.Key]: processObject(nextObject),
};
}
return result;
};
const response = {
[formatData[0].Key]: processObject(formatData[0]),
};
return response
Is this what you're after?
const input = [
{
"id": "p1", "top": 130, "left" :298, "Key": "test1",
// I've changed this from "special" to "p2"
"Next": "p2"
// rest of input is the same...
},{"id":"p2","Key":"special","specialkey":[{"key":"1","value":"p3"},{"key":"0","value":"p4"},{"key":"2","value":"p5"}],"Next":"","RepeatText": "p8","RepeatTextNew":"p9"},{"id":"p3","user":"aa","Key":"test3","Text":"hi"},{"id":"p4","Key":"special","specialkey":[{"key":"1","value":"p6"},{"key":"0","value":"p7"}]},{"id":"p5","user":"aa","Key":"test5","Text":"hi"},{"id":"p6","user":"aa","Key":"test6","Text":"hi"},{"id":"p7","user":"aa","Key":"test7","Text":"hi"},{"id":"p8","user":"aa","Key":"test8","Text":"hi"},{"id":"p9","user":"aa","Key":"test9","Text": "hi"}];
// Gets an object by its id
const getById = id => input.find(x => x.id === id);
const processObject = ({ Next, specialkey, RepeatText, RepeatTextNew, ...rest }) => {
let processedNext;
if (Next) {
const nextObject = getById(Next);
processedNext = { [nextObject.Key]: processObject(nextObject) };
}
return {
...rest,
// This spread syntax means we don't add the Next or
// specialkey property if it isn't present in the input
// object
...processedNext ? { Next: processedNext } : {},
...RepeatText
? { RepeatText: { [RepeatText]: processObject(getById(RepeatText)) } }
: {},
...RepeatTextNew
? { RepeatTextNew: { [RepeatTextNew]: processObject(getById(RepeatTextNew)) } }
: {},
...specialkey
? {
specialkey: specialkey.map(({ key, value }) => ({
key,
value: processObject(getById(value))
}))
}
: {}
};
}
console.log(processObject(input[0]));
In your code, you seem to be looking up objects by their id, so that's why I changed the first object input's Next from "special" (the Key of the p2 object) to "p2".

Reduce it array to an easier way to map

I'm developing an application and have added new items to my array: type and description.
array = [
{
"id": 1,
"description": "item1",
"date": {
"id": 1,
"name": "202001"
},
"item": {
"id": 1,
"name": "I1"
},
"type": {
"id": 1,
"name": "type1"
},
"price": 100
},
{
"id": 2,
"description": "item1",
"date": {
"id": 2,
"name": "202002"
},
"item": {
"id": 1,
"name": "I1"
},
"type": {
"id": 1,
"name": "type1"
},
"price": 200
},
{
"id": 3,
"description": "item1",
"date": {
"id": 2,
"name": "202002"
},
"item": {
"id": 2,
"name": "I2"
},
"type": {
"id": 2,
"name": "type2"
},
"price": 300
},
]
I previously did this to reduce it down to an easier way to map it:
items = array.reduce((acc, e) => {
if (!acc[e["item"]["name"]]) {
acc[e["item"]["name"]] = {
[e["date"]["name"]]: e["price"]
}
} else {
acc[e["item"]["name"]][e["date"]["name"]] = e["price"]
}
return acc
}, {})
To show the data before I did
const dates = [...new Set(Object.keys(items_dicc).map(i => Object.keys(items_dicc[i])).flat())]
{
Object.keys(items_dicc).map((item) => {
return (
<tr>
<td>{item}</td>
{dates.map((date) => <td>{items_dicc[item][date] || ''}</td>)}
</tr>
)
})
}
I need to add the description element and type.name to the above. For example for description:
description: e["description"]
To display the elements as in the table:
ITEM
DESCRIPTION
TYPE
202001
202002
I1
item1
type1
100
200
I2
item3
type2
-
300
How do I add and show?
EDIT: console.log(items_dicc[item])
{202001: 100, 202002: 200, description: "item1", type: "type1"}
202001: 100
202002: 200
description: "item1"
type: "type1"
__proto__: Object
{202002: 300, description: "item3", type: "type2"}
202002: 300
description: "item3"
type: "type2"
__proto__: Object
You can add the description and type attribute inside the reduce method like this,
array = [
{
"id": 1,
"description": "item1",
"date": {
"id": 1,
"name": "202001"
},
"item": {
"id": 1,
"name": "I1"
},
"type": {
"id": 1,
"name": "type1"
},
"price": 100
},
{
"id": 2,
"description": "item2",
"date": {
"id": 2,
"name": "202002"
},
"item": {
"id": 1,
"name": "I1"
},
"type": {
"id": 1,
"name": "type1"
},
"price": 200
},
{
"id": 3,
"description": "item3",
"date": {
"id": 2,
"name": "202002"
},
"item": {
"id": 2,
"name": "I2"
},
"type": {
"id": 2,
"name": "type2"
},
"price": 300
},
]
items = array.reduce((acc, e) => {
if (!acc[e["item"]["name"]]) {
acc[e["item"]["name"]] = {
[e["date"]["name"]]: e["price"],
'description': e['description'],
'type': e.type?.name,
}
} else {
acc[e["item"]["name"]][e["date"]["name"]] = e["price"]
}
return acc
}, {})
console.log(items);
To add the for description and name in the table,
const dates = [...new Set(Object.keys(items_dicc).map(i => Object.keys(items_dicc[i])).flat())]
{
Object.keys(items_dicc).map((item) => {
return (
<tr>
<td>{item}</td>
<td>{items_dicc[item]?.description}</td>
<td>{items_dicc[item]?.type}</td>
{dates.map((date) => <td>{items_dicc[item][date] || ''}</td>)}
</tr>
)
})
}
I have been seeing your question regarding these type of tables from yesterday. You have posted several questions with similar things. I suggest you to read some article and understand how JS array methods works instead of asking incremental questions in SO.
Asking in SO might solve your problems for now, but in the long run you will suffer as you don't seem to have a grip on how these things works.
you can simplify your solution like this.
const array = [{
"id": 1,
"description": "item1",
"date": {
"id": 1,
"name": "202001"
},
"item": {
"id": 1,
"name": "I1"
},
"type": {
"id": 1,
"name": "type1"
},
"price": 100
},
{
"id": 2,
"description": "item2",
"date": {
"id": 2,
"name": "202002"
},
"item": {
"id": 1,
"name": "I1"
},
"type": {
"id": 1,
"name": "type1"
},
"price": 200
},
{
"id": 3,
"description": "item3",
"date": {
"id": 2,
"name": "202002"
},
"item": {
"id": 2,
"name": "I2"
},
"type": {
"id": 2,
"name": "type2"
},
"price": 300
}
]
const result = array.map(item => {
return Object.keys(item).reduce((a, c) => {
if (c === "date") {
a[item[c].name] = item.price;
} else if (c !== "price" && c !== "id") {
a[c] = (typeof item[c] === "object") ? item[c].name : item[c];
}
return a;
}, {})
});
console.log(result);

how to find the ancestors of a particular object

let obj = {
"options": [
{
"id": "a",
"name": "a",
"options": [
{
"id": "a.1",
"options": [
{
"id": "a.1.1",
"name": "a.1.1"
},
{
"id": "a.1.2",
"name": "a.1.2"
},
{
"id": "a.1.3",
"name": "a.1.3"
}
]
},
{
"id": "a.2",
"name": "a.2",
"options": [
{
"id": "a.2.1",
"name": "a.2.1"
},
{
"id": "a.2.2",
"name": "a.2.2"
},
{
"id": "a.2.3",
"name": "a.2.3"
}
]
},
{
"id": "a.3",
"name": "a.3",
"options": [
{
"id": "a.3.1",
"name": "a.3.1"
},
{
"id": "a.3.2",
"name": "a.3.1"
},
{
"id": "a.3.3",
"name": "a.3.1"
}
]
}
]
},
{
"name": "b",
"id": "b",
"options": [
{
"id": "b.1",
"name": "b.1",
"options": [
{
"id": "b.1.1",
"name": "b.1.1"
},
{
"id": "b.1.2",
"name": "b.1.2"
},
{
"id": "b.1.3",
"name": "b.1.3"
}
]
},
{
"id": "b.2",
"name": "b.2",
"options": [
{
"id": "b.2.1",
"name": "b.2.1"
},
{
"id": "b.2.2",
"name": "b.2.2"
},
{
"id": "b.2.3",
"name": "b.2.3"
}
]
},
{
"id": "b.3",
"name": "b.3.1",
"options": [
{
"id": "b.3.1",
"name": "b.3.1"
},
{
"id": "b.3.2",
"name": "b.3.2"
},
{
"id": "b.3.3",
"name": "b.3.3"
}
]
}
]
},
{
"id": "c",
"name": "c",
"options": [
{
"id": "c.1",
"name": "c.1",
"options": [
{
"id": "c.1.1",
"name": "c.1.1"
},
{
"id": "c.1.2",
"name": "c.1.2"
},
{
"id": "c.1.3",
"name": "c.1.3"
}
]
},
{
"id": "c.2",
"name": "c.2",
"options": [
{
"id": "c.2.1",
"name": "c.2.1"
},
{
"id": "c.2.2",
"name": "c.2.2"
},
{
"id": "c.2.3",
"name": "c.2.3"
}
]
},
{
"id": "c.3",
"name": "c.3",
"options": [
{
"id": "c.3.1",
"name": "c.3.1"
},
{
"id": "c.3.2",
"name": "c.3.2"
},
{
"id": "c.3.3",
"name": "c.3.3"
}
]
}
]
}
]
}
" I have this object
I neeed to create a function getHierarchy, that an option ID as its input, finds the option in the
list and returns the ID of all it's parents.
for example,getHierarchy("a.1.3") should return the following result ["a","a.1","a.1.3"]
getHierarchy("c.3.3") should return the following result ["c","c.3","c.3.3"] "
assuming id is unique;
function getHierarchy(object, id, prev) {
if (!object.options) return;
for (const child of object.options) {
if(child.id === id) {
return [...prev, object.id, child.id];
}
result = getHierarchy(child, id, [...prev, object.id]);
if (result) return result;
}
}
getHierarchy(obj, "a.1.3", []);
Here an recursive solution i hope this helps you.
let obj = {
"options": [
{
"id": "a",
"name": "a",
"options": [
{
"id": "a.1",
"options": [
{
"id": "a.1.1",
"name": "a.1.1"
},
{
"id": "a.1.2",
"name": "a.1.2"
},
{
"id": "a.1.3",
"name": "a.1.3"
}
]
},
{
"id": "a.2",
"name": "a.2",
"options": [
{
"id": "a.2.1",
"name": "a.2.1"
},
{
"id": "a.2.2",
"name": "a.2.2"
},
{
"id": "a.2.3",
"name": "a.2.3"
}
]
},
{
"id": "a.3",
"name": "a.3",
"options": [
{
"id": "a.3.1",
"name": "a.3.1"
},
{
"id": "a.3.2",
"name": "a.3.1"
},
{
"id": "a.3.3",
"name": "a.3.1"
}
]
}
]
},
{
"name": "b",
"id": "b",
"options": [
{
"id": "b.1",
"name": "b.1",
"options": [
{
"id": "b.1.1",
"name": "b.1.1"
},
{
"id": "b.1.2",
"name": "b.1.2"
},
{
"id": "b.1.3",
"name": "b.1.3"
}
]
},
{
"id": "b.2",
"name": "b.2",
"options": [
{
"id": "b.2.1",
"name": "b.2.1"
},
{
"id": "b.2.2",
"name": "b.2.2"
},
{
"id": "b.2.3",
"name": "b.2.3"
}
]
},
{
"id": "b.3",
"name": "b.3.1",
"options": [
{
"id": "b.3.1",
"name": "b.3.1"
},
{
"id": "b.3.2",
"name": "b.3.2"
},
{
"id": "b.3.3",
"name": "b.3.3"
}
]
}
]
},
{
"id": "c",
"name": "c",
"options": [
{
"id": "c.1",
"name": "c.1",
"options": [
{
"id": "c.1.1",
"name": "c.1.1"
},
{
"id": "c.1.2",
"name": "c.1.2"
},
{
"id": "c.1.3",
"name": "c.1.3"
}
]
},
{
"id": "c.2",
"name": "c.2",
"options": [
{
"id": "c.2.1",
"name": "c.2.1"
},
{
"id": "c.2.2",
"name": "c.2.2"
},
{
"id": "c.2.3",
"name": "c.2.3"
}
]
},
{
"id": "c.3",
"name": "c.3",
"options": [
{
"id": "c.3.1",
"name": "c.3.1"
},
{
"id": "c.3.2",
"name": "c.3.2"
},
{
"id": "c.3.3",
"name": "c.3.3"
}
]
}
]
}
]
}
function getHierarchy(opts, path, index = 1, result = []) {
if(!opts) return result;
let objPaths = path.split(".");
let _path = objPaths.slice(0, index).join(".");
let option = opts.find(({id}) => id === _path);
if(!option) return result;
let { options, id } = option;
return getHierarchy(options, path, ++index, [...result,id]);
}
let result = getHierarchy(obj.options, "a.1.3");
console.log(result);

JSON / JavaScript - find matching values, make them into keys and create new, consolidated object

In vanilla JavaScript, how would I find unique locations from this object and make them keys, and place all items with that location as values. (can install lodash if necessary).
So this:
[
{
"item": {
"id": "cat"
},
"location": {
"id": "porch"
}
},
{
"item": {
"id": "dog"
},
"location": {
"id": "porch"
}
},
{
"item": {
"id": "snake"
},
"location": {
"id": "forest"
}
},
{
"item": {
"id": "bird"
},
"location": {
"id": "forest"
}
},
{
"item": {
"id": "beer"
},
"location": {
"id": "fridge"
}
}
]
Becomes this:
[
{
"porch": [
{
"id": "cat"
},
{
"id": "dog"
}
]
},
{
"forest": [
{
"id": "snake"
},
{
"id": "bird"
}
]
},
{
"fridge": [
{
"id": "beer"
}
]
}
]
PEN
// modified desired result
[
{
"location": {
"name": "porch",
"items": [
{
"title": "cat"
},
{
"title": "dog"
}
]
}
},
{
"location": {
"name": "forest",
"items": [
{
"title": "snake"
},
{
"title": "bird"
}
]
}
},
{
"location": {
"name": "fridge",
"items": [
{
"title": "beer"
}
]
}
}
]
let obj = [
{
"item": {
"id": "cat"
},
"location": {
"id": "porch"
}
},
{
"item": {
"id": "dog"
},
"location": {
"id": "porch"
}
},
{
"item": {
"id": "snake"
},
"location": {
"id": "forest"
}
},
{
"item": {
"id": "bird"
},
"location": {
"id": "forest"
}
},
{
"item": {
"id": "beer"
},
"location": {
"id": "fridge"
}
}
]
let result = {};
obj.forEach(({item, location}) => {
if(!result[location.id]) result[location.id] = []
result[location.id].push({title: item.id})
})
result = Object.keys(result).map(key => ({
"location": {
"name": key,
"items": result[key]
}
}))
result contains required output.

Group elements of array by sub string JavaScript

I have a list of elements like this
[{
"id": 1,
"id_team": "1.",
"name": "Name",
}, {
"id": 2,
"id_team": "2.",
"name": "Name",
}, {
"id": 3,
"id_team": "3.",
"name": "Name",
}, {
"id": 4,
"id_team": "4.",
"name": "Name",
}, {
"id": 5,
"id_team": "5.",
"name": "Name",
}, {
"id": 6,
"id_team": "2.1.",
"name": "Name",
}, {
"id": 7,
"id_team": "6.",
"name": "Name",
}, {
"id": 8,
"id_team": "1.1.",
"name": "Name",
}, {
"id": 9,
"id_team": "1.2.",
"name": "Name",
}, {
"id": 10,
"id_team": "1.3.",
"name": "Name",
}, {
"id": 11,
"id_team": "1.4.",
"name": "Name",
}]
a shown in the example, i have some string in the column id_team that are inside other string in the same column in the array
For example, the main team would be 1. then 1.1. and 1.2. and so on would be part of 1.
so the result must be like this
[{
"id": 1,
"id_team": "1.",
"name": "Name",
"subteams": [{
"id": 8,
"id_team": "1.1.",
"name": "Name",
}, {
"id": 9,
"id_team": "1.2.",
"name": "Name",
}, {
"id": 10,
"id_team": "1.3.",
"name": "Name",
}, {
"id": 11,
"id_team": "1.4.",
"name": "Name",
},],
}, {
"id": 2,
"id_team": "2.",
"name": "Name",
"subitems": [{
"id": 6,
"id_team": "2.1.",
"name": "Name",
},]
}, {
"id": 3,
"id_team": "3.",
"name": "Name",
"subitems": [],
}, {
"id": 4,
"id_team": "4.",
"name": "Name",
"subitems": [],
}, {
"id": 5,
"id_team": "5.",
"name": "Name",
"subitems": [],
}, {
"id": 7,
"id_team": "6.",
"name": "Name",
"subitems": [],
},]
it is doable? i use lodash if it would make it easier.
EDIT
I have something like this
teams.filter(item => item.id_team.length <= size).map((item) => {
const subteams = teams.filter((team) =>
team.id_team.indexOf(item.id_team) === 0 && item.id_team !== team.id_team);
console.log(subteams);
return {
...item,
subteams,
};
}) || [];
this kinda work, as it will insert in the sub teams array, but the problem is that this must work for many levels, take this example
[{
"id": 1,
"id_team": "1.",
"name": "Team Name",
"subteams": [{
"id": 8,
"id_team": "1.1.",
"name": "Team Name",
}, {
"id": 9,
"id_team": "1.2.",
"name": "Team Name",
}, {
"id": 10,
"id_team": "1.3.",
"name": "Team Name",
}, {
"id": 11,
"id_team": "1.4.",
"name": "Team Name",
}, {
"id": 12,
"id_team": "1.1.1",
"name": "Team Name",
}]
}, {
"id": 2,
"id_team": "2.",
"name": "Team Name",
"subteams": [{
"id": 6,
"id_team": "2.1.",
"name": "Team Name",
}]
}, {
"id": 3,
"id_team": "3.",
"name": "Team Name",
"subteams": []
}, {
"id": 4,
"id_team": "4.",
"name": "Team Name",
"subteams": []
}, {
"id": 5,
"id_team": "5.",
"name": "Team Name",
"subteams": []
}, {
"id": 7,
"id_team": "6.",
"name": "Team Name",
"subteams": []
}]
in this example there is a team with id_team = 1.1.1., how can i add that team to a sub team of the team with id_team 1.1. with the same logic, i tried to use the same code recursively but it didnt work.
const items = data.reduce((acc, item, index) => {
const id_team = item.id_team.split('.')[0] + '.';
const current = acc.find(record => record.id_team === id_team);
if(current) current.subteams.push(item);
else acc.push({
id: index + 1,
id_team,
subteams: [item]
});
return acc;
}, []);
let data = [{
"id": 1,
"id_team": "1.",
"name": "Name",
}, {
"id": 2,
"id_team": "2.",
"name": "Name",
}, {
"id": 3,
"id_team": "3.",
"name": "Name",
}, {
"id": 4,
"id_team": "4.",
"name": "Name",
}, {
"id": 5,
"id_team": "1.2.5.",
"name": "Name",
}, {
"id": 6,
"id_team": "2.1.",
"name": "Name",
}, {
"id": 7,
"id_team": "6.",
"name": "Name",
}, {
"id": 8,
"id_team": "1.1.",
"name": "Name",
}, {
"id": 9,
"id_team": "1.2.",
"name": "Name",
}, {
"id": 10,
"id_team": "1.3.",
"name": "Name",
}, {
"id": 11,
"id_team": "1.4.",
"name": "Name",
}];
data = data.map(node=>{
let t = node.id_team.split('.').filter(n=>n);
let parent = t.splice(0,t.length-1).join('.');
return {
...node,
parent: !!parent ? parent+'.' : null
}
});
let tree = (items, id = null) =>
items
.filter(item => item.parent === id)
.map(item => ({ ...item, subTeams: tree(items, item.id_team) }));
console.log(JSON.stringify(tree(data),null,2));
From the code of the example, i just checked if the subteams array has data, if it does, i use an auxiliar with the recursive function and assigned it to the subteams.
getSubTeams(teams, size) {
const filtered = teams.filter(item => item.id_team.length <= size);
return filtered.map((item) => {
let subteams = teams.filter((team) => team.id_team.indexOf(item.id_team) === 0 && item.id_team !== team.id_team);
if (subteams.length > 0) {
let aux = this.getSubTeams(subteams, size + 2);
subteams = [
...aux,
];
}
return {
...item,
subteams,
};
}) || [];
},

Categories