Reputation: 1455
We have 4 separate arrays each containing lists, videos, boxarts, and bookmarks respectively. Each object has a parent id, indicating its parent. We want to build an array of list objects, each with a name and a videos array. The videos array will contain the video's id, title, bookmark time, and smallest boxart url. Really important to use/debug Array.zip()
as an initial requirement and keep the initial codebase. Anyone to help?
const lists = [
{
"id": 5434364,
"name": "New Releases"
},
{
"id": 65456475,
name: "Thrillers"
}
],
videos = [
{
"listId": 5434364,
"id": 65432445,
"title": "The Chamber"
},
{
"listId": 5434364,
"id": 675465,
"title": "Fracture"
},
{
"listId": 65456475,
"id": 70111470,
"title": "Die Hard"
},
{
"listId": 65456475,
"id": 654356453,
"title": "Bad Boys"
}
],
boxarts = [
{ videoId: 65432445, width: 130, height: 200, url: "http://cdn-0.nflximg.com/images/2891/TheChamber130.jpg" },
{ videoId: 65432445, width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/TheChamber200.jpg" },
{ videoId: 675465, width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/Fracture200.jpg" },
{ videoId: 675465, width: 120, height: 200, url: "http://cdn-0.nflximg.com/images/2891/Fracture120.jpg" },
{ videoId: 675465, width: 300, height: 200, url: "http://cdn-0.nflximg.com/images/2891/Fracture300.jpg" },
{ videoId: 70111470, width: 150, height: 200, url: "http://cdn-0.nflximg.com/images/2891/DieHard150.jpg" },
{ videoId: 70111470, width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/DieHard200.jpg" },
{ videoId: 654356453, width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/BadBoys200.jpg" },
{ videoId: 654356453, width: 140, height: 200, url: "http://cdn-0.nflximg.com/images/2891/BadBoys140.jpg" }
],
bookmarks = [
{ videoId: 65432445, time: 32432 },
{ videoId: 675465, time: 3534543 },
{ videoId: 70111470, time: 645243 },
{ videoId: 654356453, time: 984934 }
];
Array.zip = function (bookmark, boxart, combinerFunction) {
let counter,
results = [];
for (counter = 0; counter < Math.min(bookmark.length, boxart.length); counter++) {
results.push(combinerFunction(bookmark[counter], boxart[counter]));
}
return results;
};
let arr1 = lists.map(function (list) {
return {
name: list.name,
videos:
videos.
filter(function (video) {
return video.listId === list.id;
}).
map(function (video) {
return Array.zip(
bookmarks.filter(function (bookmark) {
return bookmark.videoId === video.id;
}),
boxarts.filter(function (boxart) {
return boxart.videoId === video.id;
}).
reduce(function (acc, curr) {
return acc.width * acc.height < curr.width * curr.height ? acc : curr;
}),
function (bookmark, boxart) {
return { id: video.id, title: video.title, time: bookmark.time, boxart: boxart.url };
});
})
};
});
let concatArr = (function flattenDeep(arr1) {
return arr1.reduce((acc, val) => Array.isArray(val) ? acc.concat(flattenDeep(val)) : acc.concat(val), []);
})(arr1);
console.log(concatArr)
Result
Desired Output
SOLUTION
Array.zip = function (bookmark, boxart, combinerFunction) {
let counter,
results = [];
debugger
for (counter = 0; counter < Math.min(bookmark.length, boxart.length); counter++) {
results.push(combinerFunction(bookmark[counter], boxart[counter]));
}
return results;
};
let arr1 = lists.map(function (list) {
return {
name: list.name,
videos:
videos.
filter(function (video) {
return video.listId === list.id;
}).
map(function (video) {
return Array.zip(
bookmarks.filter(function (bookmark) {
return bookmark.videoId === video.id;
}),
boxarts.filter(function (boxart) {
return boxart.videoId === video.id;
}).
reduce(function (acc, curr) {
return [acc.width * acc.height < curr.width * curr.height ? acc : curr];
}),
function (bookmark, boxart) {
return { id: video.id, title: video.title, time: bookmark.time, boxart: boxart.url };
});
})
};
});
let concatArr = (function flattenDeep(arr1) {
return arr1.reduce((acc, val) => Array.isArray(val) ? acc.concat(flattenDeep(val)) : acc.concat(val), []);
})(arr1);
console.log(JSON.stringify(concatArr, null, 2))
SOLUTION Output
Upvotes: 1
Views: 118
Reputation: 84
Since you had as requirement to use zip. This solution uses lodash _.zipWith. Solution is not as optimal as the once with reduce.
let result = _.zipWith(lists, videos, boxarts, bookmarks, function(list, video, boxart, bookmark) {
if (list === undefined) return;
return {
name: list.name,
videos: videos.filter(item => item.listId === list.id).map(item => {
return {
id: item.id,
title: item.title,
boxart: boxarts.find(boxart => boxart.videoId === item.id).url,
time: bookmarks.find(bookmark => bookmark.videoId === item.id).time
}
})
}
}).filter(item => item !== undefined)
console.log(result[0]);
console.log(result[1]);
Upvotes: 0
Reputation: 50291
Use map
and find
to find an object from array using a specific key.
The below snippet contains comments, hopefully that will be useful
const lists = [{
"id": 5434364,
"name": "New Releases"
},
{
"id": 65456475,
name: "Thrillers"
}
],
videos = [{
"listId": 5434364,
"id": 65432445,
"title": "The Chamber"
},
{
"listId": 5434364,
"id": 675465,
"title": "Fracture"
},
{
"listId": 65456475,
"id": 70111470,
"title": "Die Hard"
},
{
"listId": 65456475,
"id": 654356453,
"title": "Bad Boys"
}
],
boxarts = [{
videoId: 65432445,
width: 130,
height: 200,
url: "http://cdn-0.nflximg.com/images/2891/TheChamber130.jpg"
},
{
videoId: 65432445,
width: 200,
height: 200,
url: "http://cdn-0.nflximg.com/images/2891/TheChamber200.jpg"
},
{
videoId: 675465,
width: 200,
height: 200,
url: "http://cdn-0.nflximg.com/images/2891/Fracture200.jpg"
},
{
videoId: 675465,
width: 120,
height: 200,
url: "http://cdn-0.nflximg.com/images/2891/Fracture120.jpg"
},
{
videoId: 675465,
width: 300,
height: 200,
url: "http://cdn-0.nflximg.com/images/2891/Fracture300.jpg"
},
{
videoId: 70111470,
width: 150,
height: 200,
url: "http://cdn-0.nflximg.com/images/2891/DieHard150.jpg"
},
{
videoId: 70111470,
width: 200,
height: 200,
url: "http://cdn-0.nflximg.com/images/2891/DieHard200.jpg"
},
{
videoId: 654356453,
width: 200,
height: 200,
url: "http://cdn-0.nflximg.com/images/2891/BadBoys200.jpg"
},
{
videoId: 654356453,
width: 140,
height: 200,
url: "http://cdn-0.nflximg.com/images/2891/BadBoys140.jpg"
}
],
bookmarks = [{
videoId: 65432445,
time: 32432
},
{
videoId: 675465,
time: 3534543
},
{
videoId: 70111470,
time: 645243
},
{
videoId: 654356453,
time: 984934
}
];
// using map function create an array of objects having name and videos as key. The name key will be taken from lists array and using the id from list array filter out the corrosponding objects from videos array
var newCol = lists.map(function(item) {
return {
names: item.name,
videos: videos.filter(function(videoItem) {
return item.id === videoItem.listId
})
}
})
// now iterate the newly created array and using its videoId , find the corrosponding objects from the boxart and bookmarks array
newCol.forEach(function(item) {
item.videos.forEach(function(items, index) {
let getUrl = boxarts.find(function(vidId) {
return vidId.videoId === items.id
})
// update the object by adding new key videoId & time
item.videos[index].boxarts = getUrl.url;
let getTime = bookmarks.find(function(vidId) {
return vidId.videoId === items.id
});
item.videos[index].time = getTime.time;
})
})
console.log(newCol)
Upvotes: 1
Reputation: 370729
Runtime complexity can be greatly simplified - just reduce
the time
s and boxart
s into an object indexed by video ID first, and then you can do the same thing for the video
s indexed by the list ID:
const lists=[{"id":5434364,"name":"New Releases"},{"id":65456475,name:"Thrillers"}],videos=[{"listId":5434364,"id":65432445,"title":"The Chamber"},{"listId":5434364,"id":675465,"title":"Fracture"},{"listId":65456475,"id":70111470,"title":"Die Hard"},{"listId":65456475,"id":654356453,"title":"Bad Boys"}],boxarts=[{videoId:65432445,width:130,height:200,url:"http://cdn-0.nflximg.com/images/2891/TheChamber130.jpg"},{videoId:65432445,width:200,height:200,url:"http://cdn-0.nflximg.com/images/2891/TheChamber200.jpg"},{videoId:675465,width:200,height:200,url:"http://cdn-0.nflximg.com/images/2891/Fracture200.jpg"},{videoId:675465,width:120,height:200,url:"http://cdn-0.nflximg.com/images/2891/Fracture120.jpg"},{videoId:675465,width:300,height:200,url:"http://cdn-0.nflximg.com/images/2891/Fracture300.jpg"},{videoId:70111470,width:150,height:200,url:"http://cdn-0.nflximg.com/images/2891/DieHard150.jpg"},{videoId:70111470,width:200,height:200,url:"http://cdn-0.nflximg.com/images/2891/DieHard200.jpg"},{videoId:654356453,width:200,height:200,url:"http://cdn-0.nflximg.com/images/2891/BadBoys200.jpg"},{videoId:654356453,width:140,height:200,url:"http://cdn-0.nflximg.com/images/2891/BadBoys140.jpg"}],bookmarks=[{videoId:65432445,time:32432},{videoId:675465,time:3534543},{videoId:70111470,time:645243},{videoId:654356453,time:984934}];
const timeById = bookmarks.reduce((a, { videoId, time }) => {
a[videoId] = time;
return a;
}, {});
const boxartById = boxarts.reduce((a, { videoId, url }) => {
a[videoId] = url;
return a;
}, {});
const videosByListId = videos.reduce((a, { listId, id, title }) => {
if (!a[listId]) a[listId] = [];
a[listId].push({
id,
title,
time: timeById[id],
boxart: boxartById[id],
});
return a;
}, {});
const output = lists.map(({ id, name }) => ({
name,
videos: videosByListId[id],
}));
console.log(output);
Upvotes: 1