Count how many times numbers from a list occur in a list of tupled intervals in Scala












1















Say I have a list of tuples:



 val ranges= List((1,4), (5,8), (9,10))


and a list of numbers



val nums = List(2,2,3,7,8,9)


I want to make a map from tuple in ranges to how many times a given number from nums fall into the interval of that tuple.



Output:



Map ((1,4) -> 3, (5,8) -> 2, (9,10) -> 1)


What is the best way to go about it in Scala



I have been trying to use for loops and keeping a counter but am falling short. Any help would be very much appreciated.



Best Regards










share|improve this question



























    1















    Say I have a list of tuples:



     val ranges= List((1,4), (5,8), (9,10))


    and a list of numbers



    val nums = List(2,2,3,7,8,9)


    I want to make a map from tuple in ranges to how many times a given number from nums fall into the interval of that tuple.



    Output:



    Map ((1,4) -> 3, (5,8) -> 2, (9,10) -> 1)


    What is the best way to go about it in Scala



    I have been trying to use for loops and keeping a counter but am falling short. Any help would be very much appreciated.



    Best Regards










    share|improve this question

























      1












      1








      1








      Say I have a list of tuples:



       val ranges= List((1,4), (5,8), (9,10))


      and a list of numbers



      val nums = List(2,2,3,7,8,9)


      I want to make a map from tuple in ranges to how many times a given number from nums fall into the interval of that tuple.



      Output:



      Map ((1,4) -> 3, (5,8) -> 2, (9,10) -> 1)


      What is the best way to go about it in Scala



      I have been trying to use for loops and keeping a counter but am falling short. Any help would be very much appreciated.



      Best Regards










      share|improve this question














      Say I have a list of tuples:



       val ranges= List((1,4), (5,8), (9,10))


      and a list of numbers



      val nums = List(2,2,3,7,8,9)


      I want to make a map from tuple in ranges to how many times a given number from nums fall into the interval of that tuple.



      Output:



      Map ((1,4) -> 3, (5,8) -> 2, (9,10) -> 1)


      What is the best way to go about it in Scala



      I have been trying to use for loops and keeping a counter but am falling short. Any help would be very much appreciated.



      Best Regards







      scala tuples accumulator






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Jan 18 at 14:19









      Arun ShyamArun Shyam

      2251417




      2251417
























          2 Answers
          2






          active

          oldest

          votes


















          5














          Something like this:



          val ranges = List((1, 4), (5, 8), (9, 10))
          val nums = List(2, 2, 3, 7, 8, 9)

          val occurences = ranges.map { case (l, r) => nums.count((l to r) contains _) }
          val map = (ranges zip occurences).toMap

          println(map) // Map((1,4) -> 3, (5,8) -> 2, (9,10) -> 1)


          Basically it first calculates the number of occurrences, [3, 2, 1]. From there it's easy to construct a map. And the way it calculates the occurrences is:




          • go through the list of ranges

          • transform each range into number of occurrences for that range, which is done like this :


            • how many numbers from the list nums are contained in that range?




          EDIT: Not sure why this answer is getting downvoted, perhaps I misunderstood the question somehow.






          share|improve this answer





















          • 3





            I don't know who downvoted you, it's the good answer and very scala-ish.

            – Etienne Herlaut
            Jan 18 at 14:58













          • No you didn’t misunderstand it, I believe on a large (l, r) range, contains can be a bottleneck. But I corrected for that myself 👍🏽. This was definitely right

            – Arun Shyam
            Jan 18 at 20:19













          • @Arun Shyam Yes this is inefficient, but I wanted to point you in the direction of thinking about the solution in a different way. BTW if you get a question like this on something like HackerRank, it might even be outside of time constraints and you would in that case be forced to an iterative approach with loops and counters. But whenever I can, I prefer FP solutions.

            – slouc
            Jan 19 at 14:51



















          3














          Here is an efficient single-pass solution:



          ranges
          .map(r => r -> nums.count(n => n >= r._1 && n <= r._2))
          .toMap


          This avoids the overhead of creating a list of numbers and then zipping them with the ranges in a separate step.



          This is a version that uses more Scala features but is a bit too fancy:



          (for {
          r <- ranges
          range = r._1 to r._2
          } yield r -> nums.count(range.contains)
          ).toMap


          This is also less efficient because contains has to allow for ranges with a step value and is therefore more complicated.





          And here is an even more efficient version that avoids any temporary data structures:



          val result: Map[(Int, Int), Int] =
          ranges.map(r => r -> nums.count(n => n >= r._1 && n <= r._2))(collection.breakOut)


          See this explanation of breakOut if you are not familiar with it. Using breakOut means that the map call will build the Map directly rather than creating a List that has to be converted to a Map using toMap.






          share|improve this answer

























            Your Answer






            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: "1"
            };
            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',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54255882%2fcount-how-many-times-numbers-from-a-list-occur-in-a-list-of-tupled-intervals-in%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            5














            Something like this:



            val ranges = List((1, 4), (5, 8), (9, 10))
            val nums = List(2, 2, 3, 7, 8, 9)

            val occurences = ranges.map { case (l, r) => nums.count((l to r) contains _) }
            val map = (ranges zip occurences).toMap

            println(map) // Map((1,4) -> 3, (5,8) -> 2, (9,10) -> 1)


            Basically it first calculates the number of occurrences, [3, 2, 1]. From there it's easy to construct a map. And the way it calculates the occurrences is:




            • go through the list of ranges

            • transform each range into number of occurrences for that range, which is done like this :


              • how many numbers from the list nums are contained in that range?




            EDIT: Not sure why this answer is getting downvoted, perhaps I misunderstood the question somehow.






            share|improve this answer





















            • 3





              I don't know who downvoted you, it's the good answer and very scala-ish.

              – Etienne Herlaut
              Jan 18 at 14:58













            • No you didn’t misunderstand it, I believe on a large (l, r) range, contains can be a bottleneck. But I corrected for that myself 👍🏽. This was definitely right

              – Arun Shyam
              Jan 18 at 20:19













            • @Arun Shyam Yes this is inefficient, but I wanted to point you in the direction of thinking about the solution in a different way. BTW if you get a question like this on something like HackerRank, it might even be outside of time constraints and you would in that case be forced to an iterative approach with loops and counters. But whenever I can, I prefer FP solutions.

              – slouc
              Jan 19 at 14:51
















            5














            Something like this:



            val ranges = List((1, 4), (5, 8), (9, 10))
            val nums = List(2, 2, 3, 7, 8, 9)

            val occurences = ranges.map { case (l, r) => nums.count((l to r) contains _) }
            val map = (ranges zip occurences).toMap

            println(map) // Map((1,4) -> 3, (5,8) -> 2, (9,10) -> 1)


            Basically it first calculates the number of occurrences, [3, 2, 1]. From there it's easy to construct a map. And the way it calculates the occurrences is:




            • go through the list of ranges

            • transform each range into number of occurrences for that range, which is done like this :


              • how many numbers from the list nums are contained in that range?




            EDIT: Not sure why this answer is getting downvoted, perhaps I misunderstood the question somehow.






            share|improve this answer





















            • 3





              I don't know who downvoted you, it's the good answer and very scala-ish.

              – Etienne Herlaut
              Jan 18 at 14:58













            • No you didn’t misunderstand it, I believe on a large (l, r) range, contains can be a bottleneck. But I corrected for that myself 👍🏽. This was definitely right

              – Arun Shyam
              Jan 18 at 20:19













            • @Arun Shyam Yes this is inefficient, but I wanted to point you in the direction of thinking about the solution in a different way. BTW if you get a question like this on something like HackerRank, it might even be outside of time constraints and you would in that case be forced to an iterative approach with loops and counters. But whenever I can, I prefer FP solutions.

              – slouc
              Jan 19 at 14:51














            5












            5








            5







            Something like this:



            val ranges = List((1, 4), (5, 8), (9, 10))
            val nums = List(2, 2, 3, 7, 8, 9)

            val occurences = ranges.map { case (l, r) => nums.count((l to r) contains _) }
            val map = (ranges zip occurences).toMap

            println(map) // Map((1,4) -> 3, (5,8) -> 2, (9,10) -> 1)


            Basically it first calculates the number of occurrences, [3, 2, 1]. From there it's easy to construct a map. And the way it calculates the occurrences is:




            • go through the list of ranges

            • transform each range into number of occurrences for that range, which is done like this :


              • how many numbers from the list nums are contained in that range?




            EDIT: Not sure why this answer is getting downvoted, perhaps I misunderstood the question somehow.






            share|improve this answer















            Something like this:



            val ranges = List((1, 4), (5, 8), (9, 10))
            val nums = List(2, 2, 3, 7, 8, 9)

            val occurences = ranges.map { case (l, r) => nums.count((l to r) contains _) }
            val map = (ranges zip occurences).toMap

            println(map) // Map((1,4) -> 3, (5,8) -> 2, (9,10) -> 1)


            Basically it first calculates the number of occurrences, [3, 2, 1]. From there it's easy to construct a map. And the way it calculates the occurrences is:




            • go through the list of ranges

            • transform each range into number of occurrences for that range, which is done like this :


              • how many numbers from the list nums are contained in that range?




            EDIT: Not sure why this answer is getting downvoted, perhaps I misunderstood the question somehow.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Jan 18 at 15:01

























            answered Jan 18 at 14:43









            sloucslouc

            5,6062729




            5,6062729








            • 3





              I don't know who downvoted you, it's the good answer and very scala-ish.

              – Etienne Herlaut
              Jan 18 at 14:58













            • No you didn’t misunderstand it, I believe on a large (l, r) range, contains can be a bottleneck. But I corrected for that myself 👍🏽. This was definitely right

              – Arun Shyam
              Jan 18 at 20:19













            • @Arun Shyam Yes this is inefficient, but I wanted to point you in the direction of thinking about the solution in a different way. BTW if you get a question like this on something like HackerRank, it might even be outside of time constraints and you would in that case be forced to an iterative approach with loops and counters. But whenever I can, I prefer FP solutions.

              – slouc
              Jan 19 at 14:51














            • 3





              I don't know who downvoted you, it's the good answer and very scala-ish.

              – Etienne Herlaut
              Jan 18 at 14:58













            • No you didn’t misunderstand it, I believe on a large (l, r) range, contains can be a bottleneck. But I corrected for that myself 👍🏽. This was definitely right

              – Arun Shyam
              Jan 18 at 20:19













            • @Arun Shyam Yes this is inefficient, but I wanted to point you in the direction of thinking about the solution in a different way. BTW if you get a question like this on something like HackerRank, it might even be outside of time constraints and you would in that case be forced to an iterative approach with loops and counters. But whenever I can, I prefer FP solutions.

              – slouc
              Jan 19 at 14:51








            3




            3





            I don't know who downvoted you, it's the good answer and very scala-ish.

            – Etienne Herlaut
            Jan 18 at 14:58







            I don't know who downvoted you, it's the good answer and very scala-ish.

            – Etienne Herlaut
            Jan 18 at 14:58















            No you didn’t misunderstand it, I believe on a large (l, r) range, contains can be a bottleneck. But I corrected for that myself 👍🏽. This was definitely right

            – Arun Shyam
            Jan 18 at 20:19







            No you didn’t misunderstand it, I believe on a large (l, r) range, contains can be a bottleneck. But I corrected for that myself 👍🏽. This was definitely right

            – Arun Shyam
            Jan 18 at 20:19















            @Arun Shyam Yes this is inefficient, but I wanted to point you in the direction of thinking about the solution in a different way. BTW if you get a question like this on something like HackerRank, it might even be outside of time constraints and you would in that case be forced to an iterative approach with loops and counters. But whenever I can, I prefer FP solutions.

            – slouc
            Jan 19 at 14:51





            @Arun Shyam Yes this is inefficient, but I wanted to point you in the direction of thinking about the solution in a different way. BTW if you get a question like this on something like HackerRank, it might even be outside of time constraints and you would in that case be forced to an iterative approach with loops and counters. But whenever I can, I prefer FP solutions.

            – slouc
            Jan 19 at 14:51













            3














            Here is an efficient single-pass solution:



            ranges
            .map(r => r -> nums.count(n => n >= r._1 && n <= r._2))
            .toMap


            This avoids the overhead of creating a list of numbers and then zipping them with the ranges in a separate step.



            This is a version that uses more Scala features but is a bit too fancy:



            (for {
            r <- ranges
            range = r._1 to r._2
            } yield r -> nums.count(range.contains)
            ).toMap


            This is also less efficient because contains has to allow for ranges with a step value and is therefore more complicated.





            And here is an even more efficient version that avoids any temporary data structures:



            val result: Map[(Int, Int), Int] =
            ranges.map(r => r -> nums.count(n => n >= r._1 && n <= r._2))(collection.breakOut)


            See this explanation of breakOut if you are not familiar with it. Using breakOut means that the map call will build the Map directly rather than creating a List that has to be converted to a Map using toMap.






            share|improve this answer






























              3














              Here is an efficient single-pass solution:



              ranges
              .map(r => r -> nums.count(n => n >= r._1 && n <= r._2))
              .toMap


              This avoids the overhead of creating a list of numbers and then zipping them with the ranges in a separate step.



              This is a version that uses more Scala features but is a bit too fancy:



              (for {
              r <- ranges
              range = r._1 to r._2
              } yield r -> nums.count(range.contains)
              ).toMap


              This is also less efficient because contains has to allow for ranges with a step value and is therefore more complicated.





              And here is an even more efficient version that avoids any temporary data structures:



              val result: Map[(Int, Int), Int] =
              ranges.map(r => r -> nums.count(n => n >= r._1 && n <= r._2))(collection.breakOut)


              See this explanation of breakOut if you are not familiar with it. Using breakOut means that the map call will build the Map directly rather than creating a List that has to be converted to a Map using toMap.






              share|improve this answer




























                3












                3








                3







                Here is an efficient single-pass solution:



                ranges
                .map(r => r -> nums.count(n => n >= r._1 && n <= r._2))
                .toMap


                This avoids the overhead of creating a list of numbers and then zipping them with the ranges in a separate step.



                This is a version that uses more Scala features but is a bit too fancy:



                (for {
                r <- ranges
                range = r._1 to r._2
                } yield r -> nums.count(range.contains)
                ).toMap


                This is also less efficient because contains has to allow for ranges with a step value and is therefore more complicated.





                And here is an even more efficient version that avoids any temporary data structures:



                val result: Map[(Int, Int), Int] =
                ranges.map(r => r -> nums.count(n => n >= r._1 && n <= r._2))(collection.breakOut)


                See this explanation of breakOut if you are not familiar with it. Using breakOut means that the map call will build the Map directly rather than creating a List that has to be converted to a Map using toMap.






                share|improve this answer















                Here is an efficient single-pass solution:



                ranges
                .map(r => r -> nums.count(n => n >= r._1 && n <= r._2))
                .toMap


                This avoids the overhead of creating a list of numbers and then zipping them with the ranges in a separate step.



                This is a version that uses more Scala features but is a bit too fancy:



                (for {
                r <- ranges
                range = r._1 to r._2
                } yield r -> nums.count(range.contains)
                ).toMap


                This is also less efficient because contains has to allow for ranges with a step value and is therefore more complicated.





                And here is an even more efficient version that avoids any temporary data structures:



                val result: Map[(Int, Int), Int] =
                ranges.map(r => r -> nums.count(n => n >= r._1 && n <= r._2))(collection.breakOut)


                See this explanation of breakOut if you are not familiar with it. Using breakOut means that the map call will build the Map directly rather than creating a List that has to be converted to a Map using toMap.







                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Jan 19 at 12:21

























                answered Jan 18 at 15:09









                TimTim

                5,0791317




                5,0791317






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54255882%2fcount-how-many-times-numbers-from-a-list-occur-in-a-list-of-tupled-intervals-in%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Liquibase includeAll doesn't find base path

                    How to use setInterval in EJS file?

                    Petrus Granier-Deferre