transform array of object into new array following with its child - javascript

i have an array like this
var data = [
{
name: "Movies", info: "category_name",
content: [
{ name: "Interstellar", info: "category_data" },
{ name: "Dark Knight", info: "category_data" },
]
},
{
name: "Music", info: "category_name",
content: [
{ name: "Adams", info: "category_data" },
{ name: "Nirvana", info: "category_data" },
]
},
{
name: "Places", info: "category_name",
content: [
{ name: "Jordan", info: "category_data" },
{ name: "Punjab", info: "category_data" },
]
},
]
and a want to transform it into like this
var transformedArray= [
{ name: "Movies", info: "category_name" },
{ name: "Interstellar", info: "category_data" },
{ name: "Dark Knight", info: "category_data" },
{ name: "Music", info: "category_name" },
{ name: "Adams", info: "category_data" },
{ name: "Nirvana", info: "category_data" },
{ name: "Places", info: "category_name" },
{ name: "Jordan", info: "category_data" },
{ name: "Punjab", info: "category_data" },
]
i dont know what is the keyword suitable for this case ,
i have tried mapping it into new array but it's not same like i expected
var newArr = []
var manipulate = data.map(item => {
return (
newArr.push(item),
new1.map(items => {
return (
new1.push(items)
)
})
)
})
then how to manipulate "data" into "transformedArray"

Use Array.prototype.flatMap(). If your browser or version of Node.js does not yet natively support this function, you can include a simple polyfill below, based on the specification:
if (!Array.prototype.flatMap) {
Object.defineProperty(Array.prototype, 'flatMap', {
configurable: true,
writable: true,
value: function flatMap (callback, thisArg = undefined) {
return this.reduce((array, ...args) => {
const element = callback.apply(thisArg, args);
if (Array.isArray(element)) array.push(...element);
else array.push(element);
return array;
}, []);
}
});
}
const data = [{name:'Movies',info:'category_name',content:[{name:'Interstellar',info:'category_data'},{name:'Dark Knight',info:'category_data'}]},{name:'Music',info:'category_name',content:[{name:'Adams',info:'category_data'},{name:'Nirvana',info:'category_data'}]},{name:'Places',info:'category_name',content:[{name:'Jordan',info:'category_data'},{name:'Punjab',info:'category_data'}]}];
const transformedArray = data.flatMap(({ content, ...o }) => [o, ...content]);
console.log(transformedArray);

You could do this using reduce method and spread syntax ....
var data = [{"name":"Movies","info":"category_name","content":[{"name":"Interstellar","info":"category_data"},{"name":"Dark Knight","info":"category_data"}]},{"name":"Music","info":"category_name","content":[{"name":"Adams","info":"category_data"},{"name":"Nirvana","info":"category_data"}]},{"name":"Places","info":"category_name","content":[{"name":"Jordan","info":"category_data"},{"name":"Punjab","info":"category_data"}]}]
const result = data.reduce((r, {content, ...rest}) => {
r.push({...rest}, ...content)
return r;
}, []);
console.log(result);
You can also use concat and reduce instead of spread syntax.
var data = [{"name":"Movies","info":"category_name","content":[{"name":"Interstellar","info":"category_data"},{"name":"Dark Knight","info":"category_data"}]},{"name":"Music","info":"category_name","content":[{"name":"Adams","info":"category_data"},{"name":"Nirvana","info":"category_data"}]},{"name":"Places","info":"category_name","content":[{"name":"Jordan","info":"category_data"},{"name":"Punjab","info":"category_data"}]}]
const result = data.reduce((r, {content, ...rest}) => r.concat(rest, content), []);
console.log(result);

Related

How to count the properties of an array of objects in JavaScript

var employees = [
{ name: "Josh", title: "receptionist" },
{ name: "Naila", title: "receptionist" },
{ name: "Tom", title: "doctor" },
{ name: "Becky", title: "doctor" }
];
For example on this one I would like to return
{
'doctor':2,
'receptionist':2
}
This is what I have tried:
const convert = (employees) => {
const res = {};
employees.forEach((employee) => {
const key = `${employee.title}${employee["doctor-receptionist"]}`;
if (!res[key]) {
res[key] = {...employee, count: 0 };
};
res[key].count += 1;
});
return Object.values(res);
};
console.log(convert(employees));
It returns the name of the employees, which I did not want.
I also thought about creating arrays for each kind of job title and filtering each employee from the employee array, and pushing them to their respective arrays. But I feel like there must be an easier way.
Array#reduce is the way to go:
const employees = [ { name: "Josh", title: "receptionist" }, { name: "Naila", title: "receptionist" }, { name: "Tom", title: "doctor" }, { name: "Becky", title: "doctor" } ],
summary = employees
.reduce((acc,{title}) => ({...acc,[title]:(acc[title] || 0) + 1}),{});
console.log( summary );
Just using reduce() can do it
var employees = [
{ name: "Josh", title: "receptionist" },
{ name: "Naila", title: "receptionist" },
{ name: "Tom", title: "doctor" },
{ name: "Becky", title: "doctor" }
];
let result = employees.reduce((a,c) =>{
a[c.title] = a[c.title] ? a[c.title] + 1 : 1
return a
},{})
console.log(result)
The reduce iterator was built for this kind of thing.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce
I also employ Object.values() since the way I am using reduce is to create an object to easily keep track of the data along the way. The object.values helps distill that into an array when done.
const employees = [
{ name: "Josh", title: "receptionist" },
{ name: "Naila", title: "receptionist" },
{ name: "Tom", title: "doctor" },
{ name: "Becky", title: "doctor" }];
const reduced = Object.values(employees.reduce((b,a) => {
if (!b[a.title]) b[a.title] = {title: a.title, count: 1}
else b[a.title].count++;
return b
},{}))
console.log(reduced);
you can try this on your code
const employees = [
{ name: "Josh", title: "receptionist" },
{ name: "Naila", title: "receptionist" },
{ name: "Tom", title: "doctor" },
{ name: "Becky", title: "doctor" }
]
const sumReceptionist = employees.filter((item)=>{
return item.title === 'receptionist'
}).length
const sumDoctor = employees.filter((item)=>{
return item.title === 'doctor'
}).length
let total =
{
receptionist: sumReceptionist,
doctor: sumDoctor
}
console.log(total)
I think this is what you're trying to do. You want the total of the positions from the employee list?
const Employees = [{
name: "Josh",
title: "receptionist"
},
{
name: "Naila",
title: "receptionist"
},
{
name: "Tom",
title: "doctor"
},
{
name: "Becky",
title: "doctor"
},
{
name: "Chad",
title: "doctor"
},
{
name: "Cindy",
title: "nurse"
}
];
// A forEach won't return an object or array, so we create one to modify within it
const PositionTotals = {};
Employees.forEach(employee => {
// Check if property exists. If not, create it and add one to it before continuing loop
if (!PositionTotals.hasOwnProperty(employee.title))
return PositionTotals[employee.title] = 1;
PositionTotals[employee.title]++;
})
console.log(PositionTotals);
$('#PositionTotals').html(JSON.stringify(PositionTotals, null, '\t'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>
<pre id="PositionTotals"></pre>

Filter one array by another array [duplicate]

This question already has answers here:
Filter array of objects with another array of objects
(11 answers)
Closed 1 year ago.
const items = [[{name:"p2"},{name:"p3"}, {name:"p7"},{name:"p9"},{name:"p1"}],[{name:"p6"}, {name:"p3"},{name:"p7"}, {name:"p9"},{name:"p2"}],[{name:"p3"},{name:"p6"}, {name:"p7"},{name:"p9"},{name:"p4"}],[{name:"p2"}, {name:"p3"},{name:"p1"}, {name:"p9"},{name:"p6"}]]
const findObj = [{name:"p1"},{name:"p2"},{name:"p6"}]
Find the child array of sets which have all three element from findobj object
You can easily achieve the result using filter, Set and reduceas:
const items = [
[
{ name: "p2" },
{ name: "p3" },
{ name: "p7" },
{ name: "p9" },
{ name: "p1" },
],
[
{ name: "p6" },
{ name: "p3" },
{ name: "p7" },
{ name: "p9" },
{ name: "p2" },
],
[
{ name: "p3" },
{ name: "p6" },
{ name: "p7" },
{ name: "p9" },
{ name: "p4" },
],
[
{ name: "p2" },
{ name: "p3" },
{ name: "p1" },
{ name: "p9" },
{ name: "p6" },
],
];
const findObj = [{ name: "p1" }, { name: "p2" }, { name: "p6" }];
const set = new Set(findObj.map((o) => o.name));
const result = items.filter((arr) => {
const remain = arr.reduce((acc, curr) => {
if (set.has(curr.name)) acc.add(curr.name);
return acc;
}, new Set());
return remain.size === set.size;
});
console.log(result);
const items = [[{name:"p2"},{name:"p3"}, {name:"p7"},{name:"p9"},{name:"p1"}],[{name:"p6"}, {name:"p3"},{name:"p7"}, {name:"p9"},{name:"p2"}],[{name:"p3"},{name:"p6"}, {name:"p7"},{name:"p9"},{name:"p4"}],[{name:"p2"}, {name:"p3"},{name:"p1"}, {name:"p9"},{name:"p6"}]]
const findObj = [{name:"p1"},{name:"p2"},{name:"p6"}]
const result = items.filter(item=>{
const childItem = item.map(childItem=>childItem.name);
let allExist=true;
findObj.forEach(obj=>{
if(!childItem.includes(obj.name)){
allExist=false;
}
})
return allExist;
})
console.log(result)
Using filter and get all names from each item by using map .map(prop=>prop.name) or more simple with destructuring .map(({name})=>name) and filter items that names are included in findObj
const items = [[{name:"p2"},{name:"p3"}, {name:"p7"},{name:"p9"},{name:"p1"}],[{name:"p6"}, {name:"p3"},{name:"p7"}, {name:"p9"},{name:"p2"}],[{name:"p3"},{name:"p6"}, {name:"p7"},{name:"p9"},{name:"p4"}],[{name:"p2"}, {name:"p3"},{name:"p1"}, {name:"p9"},{name:"p6"}]]
const findObj = [{name:"p1"},{name:"p2"},{name:"p6"}]
const result = items.filter(item=>{
const arrProp = item.map(prop=>prop.name)
const filtProp = findObj.map(({name})=>name)
return filtProp.every(x=>arrProp.includes(x));
})
console.log(result)

How to create array of objects from object of objects?

I have such object:
const countriesList = {
NAC: {
name: 'NAC'
},
LEVANT: {
name: 'Levant'
},
GCC: {
name: 'Gulf Cooperation Council',
iso2: 'GC',
code: '96'
},
AF: {
name: "Afghanistan",
iso2: "AF",
code: "93"
},
AL: {
name: "Albania",
iso2: "AL",
code: "355"
},
}
It's object, not array and it's important. I want to create new array, which is gonna look like that:
const result = [
{NAC: 'NAC'},
{LEVANT: 'Levant'},
{GCC: 'Gulf Cooperation Council'},
{AF: "Afghanistan"},
{AL: "Albania"}
]
I was trying to do something like that:
for (let value in countriesList) {
let temp = {
value: countriesList[value]['name']
}
this.countries.push(temp)
temp = {}
}
But instead of keys in array of objects I got value. How can I do that?
Thanks for answers!
You can map over Object.entries.
const countriesList = {
NAC: {
name: 'NAC'
},
LEVANT: {
name: 'Levant'
},
GCC: {
name: 'Gulf Cooperation Council',
iso2: 'GC',
code: '96'
},
AF: {
name: "Afghanistan",
iso2: "AF",
code: "93"
},
AL: {
name: "Albania",
iso2: "AL",
code: "355"
},
}
const res = Object.entries(countriesList).map(([key, {name}])=>({[key]: name}));
console.log(res);
Just use Object.keys then map to the name property:
Object.keys(countriesList).map(x => ({[x]: countriesList[x].name}))
You can Create and similar Array of Object with all the Keys.
const countryList = Object.entries(countriesList).map((e) => ( { [e[0]]: e[1] } ));
This Will Return Like This
[
{
NAC: {
name: 'NAC'
},
LEVANT: {
name: 'Levant'
},
GCC: {
name: 'Gulf Cooperation Council',
iso2: 'GC',
code: '96'
},
AF: {
name: "Afghanistan",
iso2: "AF",
code: "93"
},
AL: {
name: "Albania",
iso2: "AL",
code: "355"
},
}
]

Javascript filtering nested arrays

I'm trying to filter a on a nested array inside an array of objects in an Angular app. Here's a snippet of the component code -
var teams = [
{ name: 'Team1', members: [{ name: 'm1' }, { name: 'm2' }, { name: 'm3' }] },
{ name: 'Team2', members: [{ name: 'm4' }, { name: 'm5' }, { name: 'm6' }] },
{ name: 'Team3', members: [{ name: 'm7' }, { name: 'm8' }, { name: 'm9' }] }
];
What I'm trying to achieve is if I search for m5 for example my result should be -
var teams = [
{ name: 'Team1', members: [] },
{ name: 'Team2', members: [{ name: 'm5' }] },
{ name: 'Team3', members: [] }
];
So I've got teams and filteredTeams properties and in my search function I'm doing -
onSearchChange(event: any): void {
let value = event.target.value;
this.filteredTeams = this.teams.map(t => {
t.members = t.members.filter(d => d.name.toLowerCase().includes(value));
return t;
})
}
Now this does work to some extent however because I'm replacing the members it's destroying the array on each call (if that makes sense). I understand why this is happening but my question is what would be the best way to achieve this filter?
you were very close, the only thing that you did wrong was mutating the source objects in teams
basically you can use spread operator to generate a new entry and then return a whole new array with new values.
const teams = [
{ name: 'Team1', members: [{ name: 'm1' }, { name: 'm2' }, { name: 'm3' }] },
{ name: 'Team2', members: [{ name: 'm4' }, { name: 'm5' }, { name: 'm6' }] },
{ name: 'Team3', members: [{ name: 'm7' }, { name: 'm8' }, { name: 'm9' }] }
];
const value = 'm5';
const result = teams.map(t => {
const members = t.members.filter(d => d.name.toLowerCase().includes(value));
return { ...t, members };
})
console.log(result)
Check this. Instead of hard coded m5 pass your value.
const teams = [
{ name: 'Team1', members: [{ name: 'm1' }, { name: 'm2' }, { name: 'm3' }] },
{ name: 'Team2', members: [{ name: 'm4' }, { name: 'm5' }, { name: 'm6' }] },
{ name: 'Team3', members: [{ name: 'm7' }, { name: 'm8' }, { name: 'm9' }] }
];
const filteredTeams = teams.map(team => ({ name: team.name, members: team.members.filter(member => member.name.includes('m5')) }));
console.log(filteredTeams);
You are mutating the original objects, but you could assing new properties to the result object for mapping instead.
var teams = [{ name: 'Team1', members: [{ name: 'm1' }, { name: 'm2' }, { name: 'm3' }] }, { name: 'Team2', members: [{ name: 'm4' }, { name: 'm5' }, { name: 'm6' }] }, { name: 'Team3', members: [{ name: 'm7' }, { name: 'm8' }, { name: 'm9' }] }],
result = teams.map(o => Object.assign(
{},
o,
{ members: o.members.filter(({ name }) => name === 'm5') }
));
console.log(result);
console.log(teams);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Try to seperate your filter function first:
const filterTeamMembers = (teams, filterArr) => {
const useFilter = filterArr.map(x => x.toLowerCase());
return teams.map(team => ({
...team,
members: team.members.filter(member => useFilter.includes(member.name))
}))
};
// =========== And then:
onSearchChange(event: any): void {
let value = event.target.value;
this.filteredTeams = filterTeamMembers(this.teams, [value]);
}

tree search using recursion javascript

I am looking for a way to be able to search in an array, with nested arrays, a node with information. It can be seen as a tree
const data = [
{
id: '1-1',
name: "Factory",
children: [
{
id: '1-1-1',
name: "Areas",
children: [
{
id: '1-1-1-1',
name: "Sales",
children: [
{
id: '1-1-1-1-1',
name: "Bill Gates",
children:[...]
},
...
]
},
...
]
},
...
],
},
...
]
If I wanted to find the node with name: Bill Gates
Try this function, but it does not work properly
const getElements = (treeData, text) => {
return treeData.map(node => {
const textMatch = node.name.toLowerCase().includes(text.toLowerCase());
if (textMatch) {
console.log(node);
return node;
} else {
if (node.children) {
return getElements(node.children, text)
}
}
})
}
In deeper data like Bill Gates Node returns the entire TreeArray, but with all the data that does not contain the name Bill Gates as undefined
You probably don't want to use .map here, because you don't want a mutated array, you just want to find a node. Using a for loop gets the expected result:
const data = [{
id: '1-1',
name: "Factory",
children: [
{
id: '1-1-1',
name: "Areas",
children: [
{
id: '1-1-1-1',
name: "Sales",
children: [
{
id: '1-1-1-1-1',
name: "Bill Gates",
children:[]
},
]
},
]
},
]
}];
const getElements = (treeData, text) => {
for (let i=0, node = treeData[i]; node; i++) {
const textMatch = node.name.toLowerCase().includes(text.toLowerCase());
if (textMatch) {
console.log(node);
return node;
} else if (node.children) {
return getElements(node.children, text)
}
}
};
getElements(data, 'Bill Gates');

Categories

Resources