Multidimensional array of objects that retrieves the id, title, and smallest box art URL for every video Is there a way to simplify this code?

// array    
const movieLists = [
        {
            name: "New Releases",
            videos: [
                {
                    "id": 70111470,
                    "title": "Die Hard",
                    "boxarts": [
                        { width: 150, height: 200, url: "http://cdn-0.nflximg.com/images/2891/DieHard150.jpg" },
                        { width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/DieHard200.jpg" }
                    ],
                    "url": "http://api.netflix.com/catalog/titles/movies/70111470",
                    "rating": 4.0,
                    "bookmark": []
                },
                {
                    "id": 654356453,
                    "title": "Bad Boys",
                    "boxarts": [
                        { width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/BadBoys200.jpg" },
                        { width: 140, height: 200, url: "http://cdn-0.nflximg.com/images/2891/BadBoys140.jpg" }

                    ],
                    "url": "http://api.netflix.com/catalog/titles/movies/70111470",
                    "rating": 5.0,
                    "bookmark": [{ id: 432534, time: 65876586 }]
                }
            ]
        },
        {
            name: "Thrillers",
            videos: [
                {
                    "id": 65432445,
                    "title": "The Chamber",
                    "boxarts": [
                        { width: 130, height: 200, url: "http://cdn-0.nflximg.com/images/2891/TheChamber130.jpg" },
                        { width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/TheChamber200.jpg" }
                    ],
                    "url": "http://api.netflix.com/catalog/titles/movies/70111470",
                    "rating": 4.0,
                    "bookmark": []
                },
                {
                    "id": 675465,
                    "title": "Fracture",
                    "boxarts": [
                        { width: 200, height: 200, url: "http://cdn-0.nflximg.com/images/2891/Fracture200.jpg" },
                        { width: 120, height: 200, url: "http://cdn-0.nflximg.com/images/2891/Fracture120.jpg" },
                        { width: 300, height: 200, url: "http://cdn-0.nflximg.com/images/2891/Fracture300.jpg" }
                    ],
                    "url": "http://api.netflix.com/catalog/titles/movies/70111470",
                    "rating": 5.0,
                    "bookmark": [{ id: 432534, time: 65876586 }]
                }
            ]
        }
    ];

    const arr1 = movieLists
        .map(function (outterItem) {
            return outterItem.videos
                .map(function (innerItem) {
                    return [innerItem.boxarts
                        .reduce(function (acc, currentValue) {
                            if (acc.width * acc.height &lt; currentValue.width * currentValue.height) {
                                return acc
                            } else {
                                return currentValue
                            }
                        })]
                        .map(function (lastItem) {
                            return {
                                id: innerItem.id,
                                title: innerItem.title,
                                boxart: lastItem.url
                            }
                        })
                })
        })


    // flatten deep 
    const newArray = (function flattenDeep(arr1) {
            return arr1.reduce((acc, val) =&gt; Array.isArray(val) ? acc.concat(flattenDeep(val)) : acc.concat(val), []);
        })(arr1);

    console.log(newArray)
Arrow Functions and ternaries

I'll start by saying that you can simplify syntactically using ternaries and ES6 Arrow functions without losing readability. These will make the code look smaller and simpler, despite being the same solution.

It would look like this:

const arr1 = movieLists.map(outterItem =&gt; 
    outterItem.videos.map(innerItem =&gt; 
        [innerItem.boxarts
            .reduce((acc, currentValue) =&gt; acc.width * acc.height &lt; currentValue.width * currentValue.height ? 
                acc : 
                currentValue
            )
        ]
        .map(lastItem =&gt; 
            ({
                id: innerItem.id,
                title: innerItem.title,
                boxart: lastItem.url
            })
        )
    )
)


Naming

The names you gave in to some variables/parameters aren't very good and make the code somewhat hard to read. 

For instance in the maps:

.map(function (outterItem) {
    return outterItem.videos
        .map(function (innerItem) {


Both outterItem and innerItem are too vague to actually mean anything. And you can't really know what they hold unless you take a another look at the data. The outterItem is the first level object of the array, which is a sort of category object, while the innerItem would be each video of the videos array.

Solution

The solution itself seems overly complex for the problem at hand, because you do a double map, to a reduce, to a final map. And then you flatten the result with reduce. Then flatten is needed because the generated structure is deeper than you needed it to be.

A way simpler solution would be:


2 for loops to run through each video
Find the smallest box art in the video with reduce
Add the desired object to the resulting array with push


This avoids the need to flatten anything.

Following this logic, the whole code would become:

const finalVideos = []
for (let category of movieLists){
    for (let video of category.videos){
        const smallestBoxArt = video.boxarts.reduce((acc, curr) =&gt; acc.width * acc.height &lt; curr.width * curr.height ? acc : curr)
        finalVideos.push({
            id: video.id,
            title: video.title,
            boxart: smallestBoxArt.url
        });
    }
}

console.log(finalVideos)


If you feel the reduce line as a bit too long or just repeats the area code too much, you can even create a simple function for it:

const area = obj =&gt; obj.width * obj.height;


And change the reduce to use it:

const smallestBoxArt = video.boxarts.reduce((acc, curr)=&gt;area(acc) &lt; area(curr) ? acc:curr)