Reduce an array of objects based on an object array property - javascript

I need help from some JavaScript/NodeJS experts. I'm using the v14 of NodeJS.
I would like to create a function that takes as an input this kind of array (let's say that it's a list of teams):
[
{
name: 'IT',
tags: ['Department', 'Section', 'Organizational']
},
{
name: 'Male',
tags: ['Gender', 'Organizational']
},
{
name: 'Foo',
tags: []
}
]
... and returns as an output a list of teams by tag name like this:
// Output:
{
Department: 'IT',
Section: 'IT',
Organizational: 'IT, Male',
Gender: 'Male'
}
The order of object keys as well as the order of the team names don't matter. I can do this quite easily with a few lines of code, but I'm quite sure that it would be easy to do using a few of our magic map(), reduce() functions and other utilities like spreading.
Anybody can help me achieve this in an optimized way?
Thank you!

Try this:
const organization = [
{
name: 'IT',
tags: ['Department', 'Section', 'Organizational']
},
{
name: 'Male',
tags: ['Gender', 'Organizational']
},
{
name: 'Foo',
tags: []
}
]
const result = organization.reduce((acum, current) => {
current.tags.forEach(tag => {
if(acum[tag]) acum[tag] = `${acum[tag]}, ${current.name}`
else acum[tag] = current.name
})
return acum
},{})
console.log(result)

Related

how do i create a new object based off an array and another object?

I am trying to create a new object based off an existing array. I want to create a new object that show below
{ jack: 'jack', content: 'ocean'},
{ marie: 'marie', content: 'pond'},
{ james: 'james', content: 'fish biscuit'},
{paul: 'paul', content: 'cake'}
const words = ['jack','marie','james','paul']
const myUsers = [
{ name: 'jack', likes: 'ocean' },
{ name: 'marie', likes: 'pond' },
{ name: 'james', likes: 'fish biscuits' },
{ name: 'paul', likes: 'cake' }
]
const usersByLikes = words.map(word => {
const container = {};
container[word] = myUsers.map(user => user.name);
container.content = myUsers[0].likes;
return container;
})
I am not getting the correct object, but instead it returns a list.
[ { jack: [ 'shark', 'turtle', 'otter' ], content: 'ocean'}, { marie: [ 'shark', 'turtle', 'otter' ], content: 'ocean' },
{ james: [ 'shark', 'turtle', 'otter' ], content: 'ocean' },
{ paul: [ 'shark', 'turtle', 'otter' ], content: 'ocean'} ]
What is the role of words array? I think the below code will work.
const result = myUsers.map(user => ({
[user.name]: user.name,
content: user.likes
}));
console.log('result', result);
In case, if want to filter the users in word array then below solution will work for you.
const result = myUsers.filter(user => {
if (words.includes(user.name)) {
return ({
[user.name]: user.name,
content: user.likes
})
}
return false;
});
You can achieve your need with a single loop.
The answer #aravindan-venkatesan gave should give you the result you are looking for. However important to consider:
When using .map() javascript returns an array of the same length, with whatever transformations you told it to inside map().
If you want to create a brand new object, of your own construction. Try using .reduce(). This allows you to set an input variable, i.e: object, array or string.
Then loop over, and return exactly what you want, not a mapped version of the old array.
See here for more details:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce

json object from javascript nested array

I'm using a nested array with the following structure:
arr[0]["id"] = "example0";
arr[0]["name"] = "name0";
arr[1]["id"] = "example1";
arr[1]["name"] = "name1";
arr[2]["id"] = "example2";
arr[2]["name"] = "name2";
now I'm trying to get a nested Json Object from this array
arr{
{
id: example0,
name: name00,
},
{
id: example1,
name: name01,
},
{
id: example2,
name: name02,
}
}
I tought it would work with JSON.stringify(arr); but it doesen't :(
I would be really happy for a solution.
Thank you!
If you are starting out with an array that looks like this, where each subarray's first element is the id and the second element is the name:
const array = [["example0", "name00"], ["example1", "name01"], ["example2", "name02"]]
You first need to map it to an array of Objects.
const arrayOfObjects = array.map((el) => ({
id: el[0],
name: el[1]
}))
Then you can call JSON.stringify(arrayOfObjects) to get the JSON.
You need to make a valid array:
arr = [
{
id: 'example0',
name: 'name00',
},
{
id: 'example1',
name: 'name01',
},
{
id: 'example2',
name: 'name02',
}
];
console.log(JSON.stringify(arr));
Note that I am assigning the array to a variable here. Also, I use [] to create an array where your original code had {}.

javascript (reactJS) best way to access values in a child Array

I've got the following array:
This is an array of Users, and each User has an Attributes array.
Now I want to make a new array with users and only their attributes. Like this
users{
0: {
"phone_number",
"email"
}
}
What would be the best way to achieve this?
thanks
If you need Array of users which contains arrays with users attributes, then you can use Array.prototype.map method:
let users = [
{ Attributes: [ { Name: 'phone_number' }, { Name: 'email' } ] },
{ Attributes: [ { Name: 'phone_number1' }, { Name: 'email1' } ] }
];
let result = users.map((user) => user.Attributes.map((attr) => attr.Name));
console.log(result)

Filtering a list of objects by a child array in Angular 2

I have data that looks like this
[
{id: 1234,
Name: 'John',
Tags: ['tag1', 'tag2']
},
{id: 1235,
Name: 'Mike',
Tags: ['tag1', 'tag3']
}
]
I want to be able to type into a search bar and filter the data to search for related tags. There was a built in filter pipe for this in angular 1 but it looks like it has been removed in angular 2. I've been looking into custom pipes but the only way I can think to do it is with a nested loop that loops over all of the objects then loops through the tags. Am I thinking about this wrong. Is there an easier way to do this or a built in function that would work for this?
You can just use normal javascript APIs to get that behaviour:
data = [
{id: 1234,
Name: 'John',
Tags: ['tag1', 'tag2']
},
{id: 1235,
Name: 'Mike',
Tags: ['tag1', 'tag3']
}
];
filterDataByTag(searchTerm: string) {
// filter the data array, based on some condition
return this.data.filter(item => {
// only include an item in the filtered results
// if that item's Tags property includes the searchTerm
// includes is a built in array method in ES2016
return item.Tags.includes(searchTerm);
});
}
In my example, i'm harding coding the data, but you can adjust to suit your situation. The key point is the function returns a filtered list of the data based on the searchTerm, so you can just call this method each time you want to refresh your filtered list (for eg on the input event of your search field)
You should reorganize data into a reverse index store :
export interface StoreData {
Tag: string;
Peoples: People[] = [];
}
const store: StoreData[] = [];
export interface People {
id: number;
Name: string;
Tags: string[];
}
loadPeopleStore(peoples: People) {
peoples.forEach(p => {
p.Tags.forEach(t => {
let storeData = store.filter(d => d.Tag === t);
if(storeData.length == 1) {
storeData[0].Peoples.push(p);
} else {
store.push({Tag: t, Peoples[p]});
}
}
}
}
initYourPipe() {
let peoples: People[] = [
{id: 1234,
Name: 'John',
Tags: ['tag1', 'tag2']
},
{id: 1235,
Name: 'Mike',
Tags: ['tag1', 'tag3']
}
]
this.loadPeopleStore(peoples);
}

Advanced example of rxjs5 flattening

I have similar data structure to this:
let userInfo = [
{
id: 'id1',
users: [
{
name: 'userName1',
job: 'userJob',
},
{
name: 'userName2',
job: 'userJob',
}
]
},
{
id: 'id2',
users: [
{
name: 'userName3',
job: 'userJob',
},
{
name: 'userName4',
job: 'userJob',
}
]
}
]
Users are
I expected new flattened user stream with RxJS5:
{
parent: id, // parent id, where users[] come from...
name: 'userName'
job: 'userJob'
}
What is the clean functional way to archive this? Thank you...
The easiest approach would just use concatMap() to merge the internal Observable created with Rx.Observable.from with the list of users updated with their parent id.
let userInfo = [
{
id: 'id1',
users: [
{
name: 'userName1',
job: 'userJob',
},
{
name: 'userName2',
job: 'userJob',
}
]
},
{...}
];
let source = Rx.Observable.from(userInfo)
.concatMap(group => {
return Rx.Observable.from(group['users'])
.map(user => {
user['parent'] = group.id;
return user;
});
});
source.subscribe(
res => console.log(res)
);
See live demo: https://jsbin.com/miximas/2/edit?js,console
There're a lot of similar question already:
refactor fat arrow nested rxjs stream
Merge subarrays using Observables
RxJS: JSON data with an array, processing each item further in the stream

Categories

Resources