JavaScript function to convert an array to an array of strings (formatted)

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
2
down vote

favorite












Input



categories - an array of categories



[
id: 1, title: 'Smartphones' ,
id: 2, title: 'Laptops'
]


products - an array of products, linked to categories



[
id: 1, title: 'iPhone X', category_id: 1, price_min: 1200, price_max: 1700 ,
id: 2, title: 'MacBook Pro Retina 13', category_id: 2, price_min: 1500, price_max: 4500 ,
id: 3, title: 'Samsung Galaxy S8', category_id: 1, price_min: 0, price_max: 0
]


Output



[
"*Smartphones*niPhone Xn ($1200 - $1700)nSamsung Galaxy S8 (free)",
"*Laptops*nMacBook Pro Retina 13 ($1500 - $4500)"
]


Current implementation



function printPriceList (categories, products) 
return categories.map(category =>
const pcontent = products
.filter(product => product.category_id === category.id)
.map(product =>
const samePrice = product.price_min === product.price_max
const price = samePrice ? product.price_min : `$product.price_min - $product.price_max`

if (price === 0)
return `$product.title (free)`


return `$product.title ($$price)`
)
return [`*$category.title*`].concat(pcontent)
).map(cat => cat.join('n'))



I'd like to find out a way to refactor it to be more readable, easy to understand and efficient.



What can we use?



  • all the modern JS features, like a spread operator (...smth)

  • lodash






share|improve this question



























    up vote
    2
    down vote

    favorite












    Input



    categories - an array of categories



    [
    id: 1, title: 'Smartphones' ,
    id: 2, title: 'Laptops'
    ]


    products - an array of products, linked to categories



    [
    id: 1, title: 'iPhone X', category_id: 1, price_min: 1200, price_max: 1700 ,
    id: 2, title: 'MacBook Pro Retina 13', category_id: 2, price_min: 1500, price_max: 4500 ,
    id: 3, title: 'Samsung Galaxy S8', category_id: 1, price_min: 0, price_max: 0
    ]


    Output



    [
    "*Smartphones*niPhone Xn ($1200 - $1700)nSamsung Galaxy S8 (free)",
    "*Laptops*nMacBook Pro Retina 13 ($1500 - $4500)"
    ]


    Current implementation



    function printPriceList (categories, products) 
    return categories.map(category =>
    const pcontent = products
    .filter(product => product.category_id === category.id)
    .map(product =>
    const samePrice = product.price_min === product.price_max
    const price = samePrice ? product.price_min : `$product.price_min - $product.price_max`

    if (price === 0)
    return `$product.title (free)`


    return `$product.title ($$price)`
    )
    return [`*$category.title*`].concat(pcontent)
    ).map(cat => cat.join('n'))



    I'd like to find out a way to refactor it to be more readable, easy to understand and efficient.



    What can we use?



    • all the modern JS features, like a spread operator (...smth)

    • lodash






    share|improve this question























      up vote
      2
      down vote

      favorite









      up vote
      2
      down vote

      favorite











      Input



      categories - an array of categories



      [
      id: 1, title: 'Smartphones' ,
      id: 2, title: 'Laptops'
      ]


      products - an array of products, linked to categories



      [
      id: 1, title: 'iPhone X', category_id: 1, price_min: 1200, price_max: 1700 ,
      id: 2, title: 'MacBook Pro Retina 13', category_id: 2, price_min: 1500, price_max: 4500 ,
      id: 3, title: 'Samsung Galaxy S8', category_id: 1, price_min: 0, price_max: 0
      ]


      Output



      [
      "*Smartphones*niPhone Xn ($1200 - $1700)nSamsung Galaxy S8 (free)",
      "*Laptops*nMacBook Pro Retina 13 ($1500 - $4500)"
      ]


      Current implementation



      function printPriceList (categories, products) 
      return categories.map(category =>
      const pcontent = products
      .filter(product => product.category_id === category.id)
      .map(product =>
      const samePrice = product.price_min === product.price_max
      const price = samePrice ? product.price_min : `$product.price_min - $product.price_max`

      if (price === 0)
      return `$product.title (free)`


      return `$product.title ($$price)`
      )
      return [`*$category.title*`].concat(pcontent)
      ).map(cat => cat.join('n'))



      I'd like to find out a way to refactor it to be more readable, easy to understand and efficient.



      What can we use?



      • all the modern JS features, like a spread operator (...smth)

      • lodash






      share|improve this question













      Input



      categories - an array of categories



      [
      id: 1, title: 'Smartphones' ,
      id: 2, title: 'Laptops'
      ]


      products - an array of products, linked to categories



      [
      id: 1, title: 'iPhone X', category_id: 1, price_min: 1200, price_max: 1700 ,
      id: 2, title: 'MacBook Pro Retina 13', category_id: 2, price_min: 1500, price_max: 4500 ,
      id: 3, title: 'Samsung Galaxy S8', category_id: 1, price_min: 0, price_max: 0
      ]


      Output



      [
      "*Smartphones*niPhone Xn ($1200 - $1700)nSamsung Galaxy S8 (free)",
      "*Laptops*nMacBook Pro Retina 13 ($1500 - $4500)"
      ]


      Current implementation



      function printPriceList (categories, products) 
      return categories.map(category =>
      const pcontent = products
      .filter(product => product.category_id === category.id)
      .map(product =>
      const samePrice = product.price_min === product.price_max
      const price = samePrice ? product.price_min : `$product.price_min - $product.price_max`

      if (price === 0)
      return `$product.title (free)`


      return `$product.title ($$price)`
      )
      return [`*$category.title*`].concat(pcontent)
      ).map(cat => cat.join('n'))



      I'd like to find out a way to refactor it to be more readable, easy to understand and efficient.



      What can we use?



      • all the modern JS features, like a spread operator (...smth)

      • lodash








      share|improve this question












      share|improve this question




      share|improve this question








      edited Jan 8 at 0:21
























      asked Jan 8 at 0:08









      Nazar

      467




      467




















          1 Answer
          1






          active

          oldest

          votes

















          up vote
          6
          down vote



          accepted










          First impressions:



          • too much nesting, too many nested returns

          • inconsistent style, inconsistent naming

          You already recognized the potential for refactoring. The simplest possible technique for refactoring is renaming variables:



          • Your code currently uses camelCase (printPriceList, samePrice), underscores (category_id, price_min) and something else (pcontent). For me, it doesn't matter that much which style you chose as long as you use it consistently and as long as you use descriptive names.

          Other stylistic suggestions:




          • It is a habit of mine to split complex chains such as...



            const result = elements
            .filter(...)
            .map(...);


            ...into separate assignments with self-documenting names:



            const blabla = elements.filter(...);
            const result = blabla.map(...);


          • I prefer to terminate statements with semicolons instead of having to think about the rules of JavaScript's automatic semicolon insertion.


          • Instead of the 'print' prefix which signals some kind of active output e.g. to a stream, you could use e.g. 'format'.


          The most helpful refactoring is to extract code fragments that can be grouped together into their own functions:




          • Printing a product price:



            function print_product_price(price_min, price_max) 
            if (price_max === 0)
            return 'free';
            else if (price_min === price_max)
            return `$$price_min`;
            else
            return `$$price_min - $$price_max`





          • Printing a product:



            function print_product(product) 
            const price = print_product_price(product);
            return `$product.title ($price)`;




          • Printing a category:



            function print_category(category, products) 
            const category_products = products.filter(product => product.category_id === category.id);

            const category_rows = [
            `*$category.title*`,
            ...category_products.map(print_product)
            ];

            return category_rows.join('n');



            Using Lodash, the above .filter expression could be written as _.filter(products, 'category_id': category.id ) - suggested by @Gerrit0.




          • And finally printing the price list:



            function print_price_list(categories, products) 
            return categories.map(category => print_category(category, products));



          As you can see, due to extracting those functions, no secondary or deeper nesting is needed.






          share|improve this answer























            Your Answer




            StackExchange.ifUsing("editor", function ()
            return StackExchange.using("mathjaxEditing", function ()
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            );
            );
            , "mathjax-editing");

            StackExchange.ifUsing("editor", function ()
            StackExchange.using("externalEditor", function ()
            StackExchange.using("snippets", function ()
            StackExchange.snippets.init();
            );
            );
            , "code-snippets");

            StackExchange.ready(function()
            var channelOptions =
            tags: "".split(" "),
            id: "196"
            ;
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function()
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled)
            StackExchange.using("snippets", function()
            createEditor();
            );

            else
            createEditor();

            );

            function createEditor()
            StackExchange.prepareEditor(
            heartbeatType: 'answer',
            convertImagesToLinks: false,
            noModals: false,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            );



            );








             

            draft saved


            draft discarded


















            StackExchange.ready(
            function ()
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f184543%2fjavascript-function-to-convert-an-array-to-an-array-of-strings-formatted%23new-answer', 'question_page');

            );

            Post as a guest






























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes








            up vote
            6
            down vote



            accepted










            First impressions:



            • too much nesting, too many nested returns

            • inconsistent style, inconsistent naming

            You already recognized the potential for refactoring. The simplest possible technique for refactoring is renaming variables:



            • Your code currently uses camelCase (printPriceList, samePrice), underscores (category_id, price_min) and something else (pcontent). For me, it doesn't matter that much which style you chose as long as you use it consistently and as long as you use descriptive names.

            Other stylistic suggestions:




            • It is a habit of mine to split complex chains such as...



              const result = elements
              .filter(...)
              .map(...);


              ...into separate assignments with self-documenting names:



              const blabla = elements.filter(...);
              const result = blabla.map(...);


            • I prefer to terminate statements with semicolons instead of having to think about the rules of JavaScript's automatic semicolon insertion.


            • Instead of the 'print' prefix which signals some kind of active output e.g. to a stream, you could use e.g. 'format'.


            The most helpful refactoring is to extract code fragments that can be grouped together into their own functions:




            • Printing a product price:



              function print_product_price(price_min, price_max) 
              if (price_max === 0)
              return 'free';
              else if (price_min === price_max)
              return `$$price_min`;
              else
              return `$$price_min - $$price_max`





            • Printing a product:



              function print_product(product) 
              const price = print_product_price(product);
              return `$product.title ($price)`;




            • Printing a category:



              function print_category(category, products) 
              const category_products = products.filter(product => product.category_id === category.id);

              const category_rows = [
              `*$category.title*`,
              ...category_products.map(print_product)
              ];

              return category_rows.join('n');



              Using Lodash, the above .filter expression could be written as _.filter(products, 'category_id': category.id ) - suggested by @Gerrit0.




            • And finally printing the price list:



              function print_price_list(categories, products) 
              return categories.map(category => print_category(category, products));



            As you can see, due to extracting those functions, no secondary or deeper nesting is needed.






            share|improve this answer



























              up vote
              6
              down vote



              accepted










              First impressions:



              • too much nesting, too many nested returns

              • inconsistent style, inconsistent naming

              You already recognized the potential for refactoring. The simplest possible technique for refactoring is renaming variables:



              • Your code currently uses camelCase (printPriceList, samePrice), underscores (category_id, price_min) and something else (pcontent). For me, it doesn't matter that much which style you chose as long as you use it consistently and as long as you use descriptive names.

              Other stylistic suggestions:




              • It is a habit of mine to split complex chains such as...



                const result = elements
                .filter(...)
                .map(...);


                ...into separate assignments with self-documenting names:



                const blabla = elements.filter(...);
                const result = blabla.map(...);


              • I prefer to terminate statements with semicolons instead of having to think about the rules of JavaScript's automatic semicolon insertion.


              • Instead of the 'print' prefix which signals some kind of active output e.g. to a stream, you could use e.g. 'format'.


              The most helpful refactoring is to extract code fragments that can be grouped together into their own functions:




              • Printing a product price:



                function print_product_price(price_min, price_max) 
                if (price_max === 0)
                return 'free';
                else if (price_min === price_max)
                return `$$price_min`;
                else
                return `$$price_min - $$price_max`





              • Printing a product:



                function print_product(product) 
                const price = print_product_price(product);
                return `$product.title ($price)`;




              • Printing a category:



                function print_category(category, products) 
                const category_products = products.filter(product => product.category_id === category.id);

                const category_rows = [
                `*$category.title*`,
                ...category_products.map(print_product)
                ];

                return category_rows.join('n');



                Using Lodash, the above .filter expression could be written as _.filter(products, 'category_id': category.id ) - suggested by @Gerrit0.




              • And finally printing the price list:



                function print_price_list(categories, products) 
                return categories.map(category => print_category(category, products));



              As you can see, due to extracting those functions, no secondary or deeper nesting is needed.






              share|improve this answer

























                up vote
                6
                down vote



                accepted







                up vote
                6
                down vote



                accepted






                First impressions:



                • too much nesting, too many nested returns

                • inconsistent style, inconsistent naming

                You already recognized the potential for refactoring. The simplest possible technique for refactoring is renaming variables:



                • Your code currently uses camelCase (printPriceList, samePrice), underscores (category_id, price_min) and something else (pcontent). For me, it doesn't matter that much which style you chose as long as you use it consistently and as long as you use descriptive names.

                Other stylistic suggestions:




                • It is a habit of mine to split complex chains such as...



                  const result = elements
                  .filter(...)
                  .map(...);


                  ...into separate assignments with self-documenting names:



                  const blabla = elements.filter(...);
                  const result = blabla.map(...);


                • I prefer to terminate statements with semicolons instead of having to think about the rules of JavaScript's automatic semicolon insertion.


                • Instead of the 'print' prefix which signals some kind of active output e.g. to a stream, you could use e.g. 'format'.


                The most helpful refactoring is to extract code fragments that can be grouped together into their own functions:




                • Printing a product price:



                  function print_product_price(price_min, price_max) 
                  if (price_max === 0)
                  return 'free';
                  else if (price_min === price_max)
                  return `$$price_min`;
                  else
                  return `$$price_min - $$price_max`





                • Printing a product:



                  function print_product(product) 
                  const price = print_product_price(product);
                  return `$product.title ($price)`;




                • Printing a category:



                  function print_category(category, products) 
                  const category_products = products.filter(product => product.category_id === category.id);

                  const category_rows = [
                  `*$category.title*`,
                  ...category_products.map(print_product)
                  ];

                  return category_rows.join('n');



                  Using Lodash, the above .filter expression could be written as _.filter(products, 'category_id': category.id ) - suggested by @Gerrit0.




                • And finally printing the price list:



                  function print_price_list(categories, products) 
                  return categories.map(category => print_category(category, products));



                As you can see, due to extracting those functions, no secondary or deeper nesting is needed.






                share|improve this answer















                First impressions:



                • too much nesting, too many nested returns

                • inconsistent style, inconsistent naming

                You already recognized the potential for refactoring. The simplest possible technique for refactoring is renaming variables:



                • Your code currently uses camelCase (printPriceList, samePrice), underscores (category_id, price_min) and something else (pcontent). For me, it doesn't matter that much which style you chose as long as you use it consistently and as long as you use descriptive names.

                Other stylistic suggestions:




                • It is a habit of mine to split complex chains such as...



                  const result = elements
                  .filter(...)
                  .map(...);


                  ...into separate assignments with self-documenting names:



                  const blabla = elements.filter(...);
                  const result = blabla.map(...);


                • I prefer to terminate statements with semicolons instead of having to think about the rules of JavaScript's automatic semicolon insertion.


                • Instead of the 'print' prefix which signals some kind of active output e.g. to a stream, you could use e.g. 'format'.


                The most helpful refactoring is to extract code fragments that can be grouped together into their own functions:




                • Printing a product price:



                  function print_product_price(price_min, price_max) 
                  if (price_max === 0)
                  return 'free';
                  else if (price_min === price_max)
                  return `$$price_min`;
                  else
                  return `$$price_min - $$price_max`





                • Printing a product:



                  function print_product(product) 
                  const price = print_product_price(product);
                  return `$product.title ($price)`;




                • Printing a category:



                  function print_category(category, products) 
                  const category_products = products.filter(product => product.category_id === category.id);

                  const category_rows = [
                  `*$category.title*`,
                  ...category_products.map(print_product)
                  ];

                  return category_rows.join('n');



                  Using Lodash, the above .filter expression could be written as _.filter(products, 'category_id': category.id ) - suggested by @Gerrit0.




                • And finally printing the price list:



                  function print_price_list(categories, products) 
                  return categories.map(category => print_category(category, products));



                As you can see, due to extracting those functions, no secondary or deeper nesting is needed.







                share|improve this answer















                share|improve this answer



                share|improve this answer








                edited Jan 8 at 19:40









                Sam Onela

                5,88461545




                5,88461545











                answered Jan 8 at 1:59









                le_m

                1,700213




                1,700213






















                     

                    draft saved


                    draft discarded


























                     


                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function ()
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f184543%2fjavascript-function-to-convert-an-array-to-an-array-of-strings-formatted%23new-answer', 'question_page');

                    );

                    Post as a guest













































































                    Popular posts from this blog

                    Greedy Best First Search implementation in Rust

                    Function to Return a JSON Like Objects Using VBA Collections and Arrays

                    C++11 CLH Lock Implementation