简体   繁体   中英

Find 'most clicked' variant in an array of objects, given a nested array of variants in Javascript

I have an array of objects called articles . An article has 3 important properties. name , clicks , and variants . The variants property is also an array of objects that contain name (It corresponds to an article in the array articles ). What is the most efficient way to find each article's most clicked variant?

I thought maybe there was some way to use a map or spread operator, but I don't understand the syntax. I think I could create a 'dictionary' with the most clicked article for each set, but is there an easier way?

Input:

[
 {name: "article1",
 clicks: 10,
 variants: ["article2", "article3"]},

 {name: "article2",
 clicks: 7,
 variants: ["article1", "article3"]},

 {name: "article3",
 clicks: 15,
 variants: ["article1", "article2"]},

 {name: "article4",
 clicks: 3,
 variants: ["article5"]},

 {name: "article5",
 clicks: 6,
 variants: ["article4"]},
]

Desired output:

{name: "article1",
clicks: 10,
variants: ["article2", "article3"],
mostClickedVariant: "article3"}

{name: "article2",
clicks: 7,
variants: ["article1", "article3"],
mostClickedVariant: "article3"},

etc. for each article

Try this (I added all the descriptive comments in the below code snippet) :

 // Input array const arr = [ {name: "article1", clicks: 10, variants: ["article2", "article3"]}, {name: "article2", clicks: 7, variants: ["article1", "article3"]}, {name: "article3", clicks: 15, variants: ["article1", "article2"]}, {name: "article4", clicks: 3, variants: ["article5"]}, {name: "article5", clicks: 6, variants: ["article4"]}, ]; // Iterating over an input array. const res = arr.map(obj => { // Fetching variant objects in an array based on the variants name we have in the array. const variantArr = obj.variants.map(variant => arr.find(o => o.name === variant)); // Getting most clicked variant object by sorting the variantArr in desc order based on the clicks. const mostClickedVariant = variantArr.sort((a, b) => b.clicks - a.clicks)[0]; // creating a new property 'mostClickedVariant' in each obejct and assigning the name of the most clicked variant. obj.mostClickedVariant = mostClickedVariant.name; return obj; }); // Expected output console.log(res);

Welcome to StackOverflow! Please take the tour , visit the help center and read up on asking good questions . After doing some research and searching for related topics on SO, try it yourself. If you're stuck, post a minimal reproducible example of your attempt and note exactly where you're stuck. People will be glad to help.


Because someone has already posted a working answer, I won't hold back my approach, which is quite different from that one. Usually I would until the asker shows more effort.

This version does not mutate the original, just returns a copy with the new properties added. It also uses a more efficient way to find maxima, reducing the list to its maximum in O (n) time, rather than using an O (n log n) sort .

 const maxBy = (fn) => (xs) => xs .reduce ( ({m, mx}, x, _, __, v = fn (x)) => v > m ? {m: v, mx: x} : {m, mx}, {m: -Infinity} ) .mx const addMostClicked = ( articles, index = new Map (articles .map (({name, clicks}) => [name, clicks])), findMax = maxBy((x) => index .get (x)) ) => articles .map ( (article) => ({... article, mostClickedVariant: findMax (article .variants)}) ) const articles = [{name: "article1", clicks: 10, variants: ["article2", "article3"]}, {name: "article2", clicks: 7, variants: ["article1", "article3"]}, {name: "article3", clicks: 15, variants: ["article1", "article2"]}, {name: "article4", clicks: 3, variants: ["article5"]}, {name: "article5", clicks: 6, variants: ["article4"]}] console .log (addMostClicked (articles))
 .as-console-wrapper {max-height: 100% !important; top: 0}

We first create an index mapping the article names to their click counts, and, using the helper maxBy , we create a function, findMax that will find the name associated with the largest click count.

Then we simply map over the elements, returning copies with new mostClickedVariant properties determined by calling findMax with the list of variant names.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM