How do I manipulate the Javascript array? - javascript

I want to manipulate the array with sample data.
What I'm trying to do is find the movieId in the votes data, count it, get the user's name
Data Description:
movieId: votes have multiple movieIds, but only need to import one.
movieIdLength: total number of movieId's.
name: User name with the same movieId.
For example:
var votes = [{
"id": 1,
"pollId": 1,
"movieId": 2,
"name": "James"
}, {
"id": 2,
"pollId": 1,
"movieId": 3,
"name": "Laura"
}, {
"id": 3,
"pollId": 1,
"movieId": 1,
"name": "Dan"
}, {
"id": 4,
"pollId": 1,
"movieId": 3,
"name": "Steve"
}]
what I want:
var votesResult = [{
"movieId": 2,
"movieIdLength": 1,
"name": "James"
},{
"movieId": 1,
"movieIdLength": 1,
"name": "Dan"
},{
"movieId": 3,
"movieIdLength": 2,
"name": "Laura, Steve"
}]

ES6:
const a = [{
"id": 1,
"pollId": 1,
"movieId": 2,
"name": "James"
}, {
"id": 2,
"pollId": 1,
"movieId": 3,
"name": "Laura"
}, {
"id": 3,
"pollId": 1,
"movieId": 1,
"name": "Dan"
}, {
"id": 4,
"pollId": 1,
"movieId": 3,
"name": "Steve"
}]
const r = [...new Set(a.map(x => x.movieId))]
.map(x => Object.assign({movieId: x},
{movieIdLength: a.filter(l => l.movieId === x).length},
{name: a.filter(q => q.movieId === x).map(n => n.name).join(', ')}));
console.log(JSON.stringify(r, null, 2));
Less clear but without code duplication:
const a = [{
"id": 1,
"pollId": 1,
"movieId": 2,
"name": "James"
}, {
"id": 2,
"pollId": 1,
"movieId": 3,
"name": "Laura"
}, {
"id": 3,
"pollId": 1,
"movieId": 1,
"name": "Dan"
}, {
"id": 4,
"pollId": 1,
"movieId": 3,
"name": "Steve"
}]
const r = [...new Set(a.map(x => x.movieId))]
.map(x => Object.assign({movieId: x},
((f) => Object.assign({movieIdLength: f.length, name: f.map(({name}) => name).join(', ')})
)(a.filter(({movieId}) => movieId === x))
));
console.log(JSON.stringify(r, null, 2));

You need to start with an empty list for the result array, then you loop over the data and check if the movie id is in the result list. is it is, then count movieIdCount up by 1 and append the name to the name field, otherwise add a new movie to the result array, do you want the algorithm?

Related

Map new object from two objects array angular typescript baesed on id

I have something like this
export class Question {
id: string;
title: string;
description: string;
answers: Answer[];
}
export class Answer {
id: string;
text: string;
questionId: string;
}
and I have two object like this
answers = [
{
"id": 1,
"text": "some comment1",
"questionId": 1
},
{
"id": 2,
"text": "some comment2",
"questionId": 3
},
{
"id": 3,
"text": "some comment3",
"questionId": 3
}
];
questions = [
{
"id": 1,
"title": "Name1",
"description": "typicode1"
},
{
"id": 2,
"title": "Name2",
"description": "typicode2"
},
{
"id": 3,
"title": "Name3",
"description": "typicode3"
}
];
questionsAndAnswers: Question[];
Now i need to map answer to correct question on property answers
My new questionsAndAnswers should look like this
questionsAndAnswers = [{
id: 1,
title: Name1,
description: typicode1;
answers: [{
"id": 1,
"text": "some comment1",
"questionId": 1
}]
},
{
id: 2,
title: Name2,
description: typicode2;
answers: []
},
{
id: 3,
title: Name3,
description: typicode3;
answers: [{
"id": 2,
"text": "some comment2",
"questionId": 3
},
{
"id": 3,
"text": "some comment3",
"questionId": 3
}]
}
];
You could try use Array reduce with filter function. Try the following
var questions = [ { "id": 1, "title": "Name1", "description": "typicode1" }, { "id": 2, "title": "Name2", "description": "typicode2" }, { "id": 3, "title": "Name3", "description": "typicode3" } ];
var answers = [ { "id": 1, "text": "some comment1", "questionId": 1 }, { "id": 2, "text": "some comment2", "questionId": 3 }, { "id": 3, "text": "some comment3", "questionId": 3 } ];
var questionsAndAnswers = questions.reduce((acc, curr, index) => {
acc[index] = curr;
acc[index].answers = answers.filter(answer => answer.questionId === curr.id);
return acc;
}, []);
console.log(questionsAndAnswers);

Filtering an array based on multiple arrays inputs

I have three arrays.
1. Existing viewers array - existingViewers
New viewers array - newViewers
Permitted Viewers array - permittedViewers
permittedViewers is used for rendering the drop-down. And I wish to filter the newViewers and existingViewers entries from the permittedViewers.
I am doing this as three steps. And I am afraid this is not the optimized way. Can someone suggest the ideal way of doing this?
The expected result is
[
{
"id": 4,
"name": "name4"
},
{
"id": 5,
"name": "name5"
},
{
"id": 6,
"name": "name6"
}
]
let existingViewers = [{
"viewerId": 1,
"name": "name1"
},
{
"viewerId": 2,
"name": "name2"
}
],
newViewers = [
{
"viewerId": 3,
"name": "name3"
}
],
permittedViewers = [{
"id": 1,
"name": "name1"
},
{
"id": 2,
"name": "name2"
},
{
"id": 3,
"name": "name3"
},
{
"id": 4,
"name": "name4"
},
{
"id": 5,
"name": "name5"
},
{
"id": 6,
"name": "name6"
}
]
let grouped = [...existingViewers, ...newViewers]
let viewerFilter = grouped.map(viewer => { return viewer.viewerId; });
let filteredPermittedViewers = permittedViewers.filter(viewer => !viewerFilter.includes(viewer.id));
console.log(filteredPermittedViewers)
I'd make a Set of the ids of the first two arrays, and then filter the third by whether the set includes the id. (Sets have O(1) lookup time)
let existingViewers=[{"viewerId":1,"name":"name1"},{"viewerId":2,"name":"name2"}],newViewers=[{"viewerId":3,"name":"name3"}],permittedViewers=[{"id":1,"name":"name1"},{"id":2,"name":"name2"},{"id":3,"name":"name3"},{"id":4,"name":"name4"},{"id":5,"name":"name5"},{"id":6,"name":"name6"}];
const ids = new Set([...existingViewers, ...newViewers].map(({ viewerId }) => viewerId));
const output = permittedViewers.filter(({ id }) => !ids.has(id));
console.log(output);
You can compress all three statements into a single statement -- just replace the variable name with the statement that creates it:
let existingViewers = [{
"viewerId": 1,
"name": "name1"
},
{
"viewerId": 2,
"name": "name2"
}
],
newViewers = [
{
"viewerId": 3,
"name": "name3"
}
],
permittedViewers = [{
"id": 1,
"name": "name1"
},
{
"id": 2,
"name": "name2"
},
{
"id": 3,
"name": "name3"
},
{
"id": 4,
"name": "name4"
},
{
"id": 5,
"name": "name5"
},
{
"id": 6,
"name": "name6"
}
]
let filteredPermittedViewers = permittedViewers.filter(viewer => ! [...existingViewers, ...newViewers].map(viewer => viewer.viewerId).includes(viewer.id));
console.log(filteredPermittedViewers)

How to flatten and merge nested array from each of child array

So i have this data:
let data = [
{
"purchase_id": 1,
"product": [
{
"name": "A",
"id": 1,
"transactions": [
{
"price": 5,
"qty": 2
},
{
"price": 10,
"qty": 2
}
]
},
{
"name": "B",
"id": 2,
"transactions": [
{
"price": 3,
"qty": 4
}
]
}
]
},
{
"purchase_id": 2,
"product": [
{
"name": "C",
"id": 3,
"transactions": [
{
"price": 5,
"qty": 2
}
]
},
{
"name": "D",
"id": 4,
"transactions": [
{
"price": 3,
"qty": 4
}
]
}
]
}
]
And i want to flatten array from each data.product.transactions data:
"transactions": [
{
"price",
"qty"
}
]
Expected output is:
[
{
"purchase_id": 1,
"name": "A",
"id": 1,
"price": 5,
"qty": 2
},
{
"purchase_id": 1,
"name": "A",
"id": 1,
"price": 10,
"qty": 2
},
{
"purchase_id": 1,
"name": "B",
"id": 2,
"price": 3,
"qty": 4
},
{
"purchase_id": 2,
"name": "C",
"id": 3,
"price": 5,
"qty": 2
},
{
"purchase_id": 2,
"name": "D",
"id": 4,
"price": 3,
"qty": 4
},
]
I have tried to use object assign, reduce but my code doesn't work. Thank you
Use nested Array.map() to create the objects, and spread into Array.concat() to flatten the sub-arrays at each level:
const data = [{"purchase_id":1,"product":[{"name":"A","id":1,"transactions":[{"price":5,"qty":2},{"price":10,"qty":2}]},{"name":"B","id":2,"transactions":[{"price":3,"qty":4}]}]},{"purchase_id":2,"product":[{"name":"C","id":3,"transactions":[{"price":5,"qty":2}]},{"name":"D","id":4,"transactions":[{"price":3,"qty":4}]}]}];
const result = [].concat(...data.map(({ purchase_id, product }) =>
[].concat(...product.map(({ name, id, transactions }) =>
transactions.map((o) => ({
purchase_id,
name,
id,
...o
})
)))));
console.log(result);
If you want to avoid the temp sub-arrays, and the flattering, use nested Array.forEach() calls, and push the created objects to a predefined array:
const data = [{"purchase_id":1,"product":[{"name":"A","id":1,"transactions":[{"price":5,"qty":2},{"price":10,"qty":2}]},{"name":"B","id":2,"transactions":[{"price":3,"qty":4}]}]},{"purchase_id":2,"product":[{"name":"C","id":3,"transactions":[{"price":5,"qty":2}]},{"name":"D","id":4,"transactions":[{"price":3,"qty":4}]}]}];
const result = [];
data.forEach(({ purchase_id, product }) =>
product.forEach(({ name, id, transactions }) =>
transactions.forEach((o) => result.push({
purchase_id,
name,
id,
...o
})
)));
console.log(result);
var arr = [];
data.forEach(x => {
x.product.forEach(y => {
y.transactions.forEach(z => {
z["name"] = y.name;
z["id"] = y.id;
z["purchase_id"] = x.purchase_id;
arr.push(z);
});
})
});
console.log(arr);

Making one to many relation array in JavaScript

I have two arrays of objects:
var a = [{
"id": 1,
"name": "q"
},
{
"id": 2,
"name": "l"
}]
and another is
var b = [{
"id": 3,
"sub": 1,
"name": "ni"
},
{
"id": 4,
"sub": 2,
"name": "bh"
}]
Here sub is the id in a
I need to have a new array which will look like this:
var c = [
{
"id":1,
"name":"q",
"map":[
{
"id":3,
"name":"ni"
}
]
},
{
"id":2,
"name":"l",
"map":[
{
"id":4,
"name":"bh"
}
]
}
]
How can I do that in JavaScript?
I am using underscore in my project.
In plain Javascript you could use Array#map, Array#forEach and a hash table.
var a = [{ "id": 1, "name": "q" }, { "id": 2, "name": "l" }],
b = [{ "id": 3, "sub": 1, "name": "ni" }, { "id": 4, "sub": 2, "name": "bh" }],
hash = Object.create(null),
result = a.map(function (a, i) {
hash[a.id] = { id: a.id, name: a.name };
return hash[a.id];
}, hash);
b.forEach(function (a) {
hash[a.sub].map = hash[a.sub].map || [];
hash[a.sub].map.push({ id: a.id, name: a.name });
}, hash);
console.log(result);
ES6
var a = [{ "id": 1, "name": "q" }, { "id": 2, "name": "l" }],
b = [{ "id": 3, "sub": 1, "name": "ni" }, { "id": 4, "sub": 2, "name": "bh" }],
hash = Object.create(null),
result = a.map((hash => a => hash[a.id] = { id: a.id, name: a.name, map: [] })(hash));
b.forEach((hash => a => hash[a.sub].map.push({ id: a.id, name: a.name }))(hash));
console.log(result);
You can do it with the help of map function and then use the find function to search the data from the other array.
var b = [{
"id": 3,
"sub": 1,
"name": "ni"
}, {
"id": 4,
"sub": 2,
"name": "bh"
}];
var a = [{
"id": 1,
"name": "q"
}, {
"id": 2,
"name": "l"
}];
var final = _.map(b, function(d) {
return {
id: d.name,
name: d.name,
map: _.find(a, function(adata) {
return adata.id == d.sub; //use underscore find to get the relevant data from array a
})
}
});
console.log(final);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

lodash merge and combine objects

I have an array of objects as below that I read from my database using sequelize ORM:
I want to have all my videos from a section, but the better I can return using sequelize is :
[{
"id": 2,
"name": "Ru",
"subsection": 1,
"Video": {
"id": 11,
"source": "sourrrccrsss22222",
"videoSubSection": 2
}
},
{
"id": 2,
"name": "Ru",
"subsection": 1,
"Video": {
"id": 12,
"source": "sourrrccrsss111",
"videoSubSection": 2
}
},
{
"id": 1,
"name": "Oc",
"subsection": 1,
"Video": {
"id": 13,
"source": "sourrrcc",
"videoSubSection": 1
}
},
{
"id": 1,
"name": "Oc",
"subsection": 1,
"Video": {
"id": 14,
"source": "sourrrcc",
"videoSubSection": 1
}
}]
Is there a way to merge and combine the objects in my array to obtain something like this :
[{
"id": 2,
"name": "Ru",
"subsection": 1,
"Video": [{
"id": 11,
"source": "sourrrccrsss22222",
"videoSubSection": 2
},{
"id": 12,
"source": "sourrrccrsss111",
"videoSubSection": 2
}]
},
{
"id": 1,
"name": "Oc",
"subsection": 1,
"Video": [{
"id": 13,
"source": "sourrrcc",
"videoSubSection": 1
},{
"id": 14,
"source": "sourrrcc",
"videoSubSection": 1
}]
}
The function that approach the most is _.mergeWith(object, sources, customizer) but the main problem I have is that I have on object and need to merge this object.
In plain Javascript, you can use Array#forEach() with a temporary object for the arrays.
var data = [{ id: 2, name: "Ru", subsection: 1, Video: { id: 11, source: "sourrrccrsss22222", VideoSubSection: 2 } }, { id: 2, name: "Ru", subsection: 1, Video: { id: 12, source: "sourrrccrsss111", VideoSubSection: 2 } }, { id: 1, name: "Oc", subsection: 1, Video: { id: 13, source: "sourrrcc", VideoSubSection: 1 } }, { id: 1, name: "Oc", subsection: 1, Video: { id: 14, source: "sourrrcc", VideoSubSection: 1 } }],
merged = function (data) {
var r = [], o = {};
data.forEach(function (a) {
if (!(a.id in o)) {
o[a.id] = [];
r.push({ id: a.id, name: a.name, subsection: a.subsection, Video: o[a.id] });
}
o[a.id].push(a.Video);
});
return r;
}(data);
document.write('<pre>' + JSON.stringify(merged, 0, 4) + '</pre>');
Maybe try transform():
_.transform(data, (result, item) => {
let found;
if ((found = _.find(result, { id: item.id }))) {
found.Video.push(item.Video);
} else {
result.push(_.defaults({ Video: [ item.Video ] }, item));
}
}, []);
Using reduce() would work here as well, but transform() is less verbose.
You can do it this way (test is your db output here)
var result = [];
var map = [];
_.forEach(test, (o) => {
var temp = _.clone(o);
delete o.Video;
if (!_.some(map, o)) {
result.push(_.extend(o, {Video: [temp.Video]}));
map.push(o);
} else {
var index = _.findIndex(map, o);
result[index].Video.push(temp.Video);
}
});
console.log(result); // outputs what you want.

Categories

Resources