scala getting read,write and reject records with simplified regex












0















I'm working on a log file to parse the read/written/rejected records using scala and convert them into a Map. The values are present in different lines - "read" followed by "written" in next line and then "rejected"..



The snippet of the code I'm using is



val log_text =
"""
|server.net|Wed Apr 8 05:44:24 2018|acct_reformat.000||finish|
| 120 records ( 7200 bytes) read
| 100 records ( 6000 bytes) written
| 20 records ( 1200 bytes) rejected|
|server.net|Wed Apr 8 05:44:24 2018|acct_reformat_rfm_logs
""".stripMargin

val read_pat = """(d+) (records) (.*)""".r
val write_pat = """(?s)records .*? (d+) (records)(.*)""".r
val reject_pat = """(?s).* (d+) (records)""".r

val read_recs = read_pat.findAllIn(log_text).matchData.map( m=> m.subgroups(0) ).take(1).mkString
val write_recs = write_pat.findAllIn(log_text).matchData.map( m=> m.subgroups(0) ).take(1).mkString
val reject_recs = reject_pat.findAllIn(log_text).matchData.map( m=> m.subgroups(0) ).take(1).mkString

val log_summ = List("Read",read_recs,"Write",write_recs,"Reject",reject_recs).sliding(2,2).map( p => p match { case List(x,y) => (x,y)}).toMap


which results in



log_summ: scala.collection.immutable.Map[String,String] = Map(Read -> 120, Write -> 100, Reject -> 20)


Somehow I feel, I'm doing it in a roundabout/redundant way.. Is there a better way to accomplish this?.










share|improve this question



























    0















    I'm working on a log file to parse the read/written/rejected records using scala and convert them into a Map. The values are present in different lines - "read" followed by "written" in next line and then "rejected"..



    The snippet of the code I'm using is



    val log_text =
    """
    |server.net|Wed Apr 8 05:44:24 2018|acct_reformat.000||finish|
    | 120 records ( 7200 bytes) read
    | 100 records ( 6000 bytes) written
    | 20 records ( 1200 bytes) rejected|
    |server.net|Wed Apr 8 05:44:24 2018|acct_reformat_rfm_logs
    """.stripMargin

    val read_pat = """(d+) (records) (.*)""".r
    val write_pat = """(?s)records .*? (d+) (records)(.*)""".r
    val reject_pat = """(?s).* (d+) (records)""".r

    val read_recs = read_pat.findAllIn(log_text).matchData.map( m=> m.subgroups(0) ).take(1).mkString
    val write_recs = write_pat.findAllIn(log_text).matchData.map( m=> m.subgroups(0) ).take(1).mkString
    val reject_recs = reject_pat.findAllIn(log_text).matchData.map( m=> m.subgroups(0) ).take(1).mkString

    val log_summ = List("Read",read_recs,"Write",write_recs,"Reject",reject_recs).sliding(2,2).map( p => p match { case List(x,y) => (x,y)}).toMap


    which results in



    log_summ: scala.collection.immutable.Map[String,String] = Map(Read -> 120, Write -> 100, Reject -> 20)


    Somehow I feel, I'm doing it in a roundabout/redundant way.. Is there a better way to accomplish this?.










    share|improve this question

























      0












      0








      0








      I'm working on a log file to parse the read/written/rejected records using scala and convert them into a Map. The values are present in different lines - "read" followed by "written" in next line and then "rejected"..



      The snippet of the code I'm using is



      val log_text =
      """
      |server.net|Wed Apr 8 05:44:24 2018|acct_reformat.000||finish|
      | 120 records ( 7200 bytes) read
      | 100 records ( 6000 bytes) written
      | 20 records ( 1200 bytes) rejected|
      |server.net|Wed Apr 8 05:44:24 2018|acct_reformat_rfm_logs
      """.stripMargin

      val read_pat = """(d+) (records) (.*)""".r
      val write_pat = """(?s)records .*? (d+) (records)(.*)""".r
      val reject_pat = """(?s).* (d+) (records)""".r

      val read_recs = read_pat.findAllIn(log_text).matchData.map( m=> m.subgroups(0) ).take(1).mkString
      val write_recs = write_pat.findAllIn(log_text).matchData.map( m=> m.subgroups(0) ).take(1).mkString
      val reject_recs = reject_pat.findAllIn(log_text).matchData.map( m=> m.subgroups(0) ).take(1).mkString

      val log_summ = List("Read",read_recs,"Write",write_recs,"Reject",reject_recs).sliding(2,2).map( p => p match { case List(x,y) => (x,y)}).toMap


      which results in



      log_summ: scala.collection.immutable.Map[String,String] = Map(Read -> 120, Write -> 100, Reject -> 20)


      Somehow I feel, I'm doing it in a roundabout/redundant way.. Is there a better way to accomplish this?.










      share|improve this question














      I'm working on a log file to parse the read/written/rejected records using scala and convert them into a Map. The values are present in different lines - "read" followed by "written" in next line and then "rejected"..



      The snippet of the code I'm using is



      val log_text =
      """
      |server.net|Wed Apr 8 05:44:24 2018|acct_reformat.000||finish|
      | 120 records ( 7200 bytes) read
      | 100 records ( 6000 bytes) written
      | 20 records ( 1200 bytes) rejected|
      |server.net|Wed Apr 8 05:44:24 2018|acct_reformat_rfm_logs
      """.stripMargin

      val read_pat = """(d+) (records) (.*)""".r
      val write_pat = """(?s)records .*? (d+) (records)(.*)""".r
      val reject_pat = """(?s).* (d+) (records)""".r

      val read_recs = read_pat.findAllIn(log_text).matchData.map( m=> m.subgroups(0) ).take(1).mkString
      val write_recs = write_pat.findAllIn(log_text).matchData.map( m=> m.subgroups(0) ).take(1).mkString
      val reject_recs = reject_pat.findAllIn(log_text).matchData.map( m=> m.subgroups(0) ).take(1).mkString

      val log_summ = List("Read",read_recs,"Write",write_recs,"Reject",reject_recs).sliding(2,2).map( p => p match { case List(x,y) => (x,y)}).toMap


      which results in



      log_summ: scala.collection.immutable.Map[String,String] = Map(Read -> 120, Write -> 100, Reject -> 20)


      Somehow I feel, I'm doing it in a roundabout/redundant way.. Is there a better way to accomplish this?.







      scala scala-collections






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 22 '18 at 13:27









      stack0114106stack0114106

      3,1642417




      3,1642417
























          3 Answers
          3






          active

          oldest

          votes


















          2














          Given the similarity of the read/write/reject text, you could simplify the multiple Regex matching patterns into a generic one and use zip to generate your Map, as shown below:



          val pattern = """(d+) records .*""".r

          val keys = List("Read", "Write", "Reject")

          val values = pattern.findAllIn(log_text).matchData.map(_.subgroups(0)).toList
          // values: List[String] = List(120, 100, 20)

          val log_summ = (keys zip values).toMap
          // log_summ: scala.collection.immutable.Map[String,String] =
          // Map(Read -> 120, Write -> 100, Reject -> 20)





          share|improve this answer
























          • Great answer!..you simplified greatly..

            – stack0114106
            Nov 22 '18 at 19:35



















          1














          Looks fine to me. Just three things to improve:



          1) IntelliJ is your friend. It gives you two intentions immediately:





          • m.subgroups(0) -> m.subgroups.head


          • map(p => p match { case List(x, y) => (x, y) }) -> map { case List(x, y) => (x, y) }


          2) DRY. Don't repeat read/write/reject related code three times. Just keep it somewhere once. E.g.:



          case class Processor(name: String, patternString: String) {
          lazy val pattern: Regex = patternString.r
          }

          val processors = Seq(
          Processor("Read", """(d+) (records) (.*)"""),
          Processor("Write", """(?s)records .*? (d+) (records)(.*)"""),
          Processor("Reject", """(?s).* (d+) (records)"""),
          )

          def read_recs(processor: Processor) = processor.pattern.findAllIn(log_text).matchData.map(m => m.subgroups.head).take(1).mkString


          3) List[Tuple2] can be converted to a Map with a simple toMap



          val log_summ = processors.map(processor => processor.name -> read_recs(processor)).toMap





          share|improve this answer
























          • This also works.. thanks for the answer..

            – stack0114106
            Nov 22 '18 at 19:36



















          1














          It can be done in a single pass if you're willing to use the log's wording for the Map keys.



          val Pattern = raw"(d+) records .*) ([^|]+)".r.unanchored

          log_text.split("n").flatMap{
          case Pattern(num, typ) => Some(typ -> num)
          case _ => None
          }.toMap
          //res0: immutable.Map[String,String] = Map(read -> 120, written -> 100, rejected -> 20)





          share|improve this answer
























          • Could you please add explanation on the unanchored?.. right now in travel will check tomorrow.. thanks for the answer..

            – stack0114106
            Nov 22 '18 at 19:55











          • btw.. why flatMap after the split? Will not just map() do the work?..

            – stack0114106
            Nov 22 '18 at 19:57











          • unanchored: Regex patterns in Scala are, by default, "anchored" to the start/end of the string, meaning, "This pattern describes the entire string from beginning to end." "unanchored", on the other hand, means, "This pattern describes some part of the string, which might, or might not, include the start and/or end."

            – jwvh
            Nov 22 '18 at 21:09











          • flatMap: Notice that I'm returning an Option (Some or None) from the map operation. If I had used map() the return type would be Array[Option[(String,String)]], which can't be turned into a Map. You can use .flatten to flatten a collection of Option[X] elements into a collection of just [X] elements, and all the None values will disappear. flatMap() is the combination of map(...).flatten.

            – jwvh
            Nov 22 '18 at 21:18













          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%2f53432057%2fscala-getting-read-write-and-reject-records-with-simplified-regex%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          3 Answers
          3






          active

          oldest

          votes








          3 Answers
          3






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes









          2














          Given the similarity of the read/write/reject text, you could simplify the multiple Regex matching patterns into a generic one and use zip to generate your Map, as shown below:



          val pattern = """(d+) records .*""".r

          val keys = List("Read", "Write", "Reject")

          val values = pattern.findAllIn(log_text).matchData.map(_.subgroups(0)).toList
          // values: List[String] = List(120, 100, 20)

          val log_summ = (keys zip values).toMap
          // log_summ: scala.collection.immutable.Map[String,String] =
          // Map(Read -> 120, Write -> 100, Reject -> 20)





          share|improve this answer
























          • Great answer!..you simplified greatly..

            – stack0114106
            Nov 22 '18 at 19:35
















          2














          Given the similarity of the read/write/reject text, you could simplify the multiple Regex matching patterns into a generic one and use zip to generate your Map, as shown below:



          val pattern = """(d+) records .*""".r

          val keys = List("Read", "Write", "Reject")

          val values = pattern.findAllIn(log_text).matchData.map(_.subgroups(0)).toList
          // values: List[String] = List(120, 100, 20)

          val log_summ = (keys zip values).toMap
          // log_summ: scala.collection.immutable.Map[String,String] =
          // Map(Read -> 120, Write -> 100, Reject -> 20)





          share|improve this answer
























          • Great answer!..you simplified greatly..

            – stack0114106
            Nov 22 '18 at 19:35














          2












          2








          2







          Given the similarity of the read/write/reject text, you could simplify the multiple Regex matching patterns into a generic one and use zip to generate your Map, as shown below:



          val pattern = """(d+) records .*""".r

          val keys = List("Read", "Write", "Reject")

          val values = pattern.findAllIn(log_text).matchData.map(_.subgroups(0)).toList
          // values: List[String] = List(120, 100, 20)

          val log_summ = (keys zip values).toMap
          // log_summ: scala.collection.immutable.Map[String,String] =
          // Map(Read -> 120, Write -> 100, Reject -> 20)





          share|improve this answer













          Given the similarity of the read/write/reject text, you could simplify the multiple Regex matching patterns into a generic one and use zip to generate your Map, as shown below:



          val pattern = """(d+) records .*""".r

          val keys = List("Read", "Write", "Reject")

          val values = pattern.findAllIn(log_text).matchData.map(_.subgroups(0)).toList
          // values: List[String] = List(120, 100, 20)

          val log_summ = (keys zip values).toMap
          // log_summ: scala.collection.immutable.Map[String,String] =
          // Map(Read -> 120, Write -> 100, Reject -> 20)






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 22 '18 at 14:22









          Leo CLeo C

          10.8k2618




          10.8k2618













          • Great answer!..you simplified greatly..

            – stack0114106
            Nov 22 '18 at 19:35



















          • Great answer!..you simplified greatly..

            – stack0114106
            Nov 22 '18 at 19:35

















          Great answer!..you simplified greatly..

          – stack0114106
          Nov 22 '18 at 19:35





          Great answer!..you simplified greatly..

          – stack0114106
          Nov 22 '18 at 19:35













          1














          Looks fine to me. Just three things to improve:



          1) IntelliJ is your friend. It gives you two intentions immediately:





          • m.subgroups(0) -> m.subgroups.head


          • map(p => p match { case List(x, y) => (x, y) }) -> map { case List(x, y) => (x, y) }


          2) DRY. Don't repeat read/write/reject related code three times. Just keep it somewhere once. E.g.:



          case class Processor(name: String, patternString: String) {
          lazy val pattern: Regex = patternString.r
          }

          val processors = Seq(
          Processor("Read", """(d+) (records) (.*)"""),
          Processor("Write", """(?s)records .*? (d+) (records)(.*)"""),
          Processor("Reject", """(?s).* (d+) (records)"""),
          )

          def read_recs(processor: Processor) = processor.pattern.findAllIn(log_text).matchData.map(m => m.subgroups.head).take(1).mkString


          3) List[Tuple2] can be converted to a Map with a simple toMap



          val log_summ = processors.map(processor => processor.name -> read_recs(processor)).toMap





          share|improve this answer
























          • This also works.. thanks for the answer..

            – stack0114106
            Nov 22 '18 at 19:36
















          1














          Looks fine to me. Just three things to improve:



          1) IntelliJ is your friend. It gives you two intentions immediately:





          • m.subgroups(0) -> m.subgroups.head


          • map(p => p match { case List(x, y) => (x, y) }) -> map { case List(x, y) => (x, y) }


          2) DRY. Don't repeat read/write/reject related code three times. Just keep it somewhere once. E.g.:



          case class Processor(name: String, patternString: String) {
          lazy val pattern: Regex = patternString.r
          }

          val processors = Seq(
          Processor("Read", """(d+) (records) (.*)"""),
          Processor("Write", """(?s)records .*? (d+) (records)(.*)"""),
          Processor("Reject", """(?s).* (d+) (records)"""),
          )

          def read_recs(processor: Processor) = processor.pattern.findAllIn(log_text).matchData.map(m => m.subgroups.head).take(1).mkString


          3) List[Tuple2] can be converted to a Map with a simple toMap



          val log_summ = processors.map(processor => processor.name -> read_recs(processor)).toMap





          share|improve this answer
























          • This also works.. thanks for the answer..

            – stack0114106
            Nov 22 '18 at 19:36














          1












          1








          1







          Looks fine to me. Just three things to improve:



          1) IntelliJ is your friend. It gives you two intentions immediately:





          • m.subgroups(0) -> m.subgroups.head


          • map(p => p match { case List(x, y) => (x, y) }) -> map { case List(x, y) => (x, y) }


          2) DRY. Don't repeat read/write/reject related code three times. Just keep it somewhere once. E.g.:



          case class Processor(name: String, patternString: String) {
          lazy val pattern: Regex = patternString.r
          }

          val processors = Seq(
          Processor("Read", """(d+) (records) (.*)"""),
          Processor("Write", """(?s)records .*? (d+) (records)(.*)"""),
          Processor("Reject", """(?s).* (d+) (records)"""),
          )

          def read_recs(processor: Processor) = processor.pattern.findAllIn(log_text).matchData.map(m => m.subgroups.head).take(1).mkString


          3) List[Tuple2] can be converted to a Map with a simple toMap



          val log_summ = processors.map(processor => processor.name -> read_recs(processor)).toMap





          share|improve this answer













          Looks fine to me. Just three things to improve:



          1) IntelliJ is your friend. It gives you two intentions immediately:





          • m.subgroups(0) -> m.subgroups.head


          • map(p => p match { case List(x, y) => (x, y) }) -> map { case List(x, y) => (x, y) }


          2) DRY. Don't repeat read/write/reject related code three times. Just keep it somewhere once. E.g.:



          case class Processor(name: String, patternString: String) {
          lazy val pattern: Regex = patternString.r
          }

          val processors = Seq(
          Processor("Read", """(d+) (records) (.*)"""),
          Processor("Write", """(?s)records .*? (d+) (records)(.*)"""),
          Processor("Reject", """(?s).* (d+) (records)"""),
          )

          def read_recs(processor: Processor) = processor.pattern.findAllIn(log_text).matchData.map(m => m.subgroups.head).take(1).mkString


          3) List[Tuple2] can be converted to a Map with a simple toMap



          val log_summ = processors.map(processor => processor.name -> read_recs(processor)).toMap






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 22 '18 at 13:55









          ygorygor

          1,112615




          1,112615













          • This also works.. thanks for the answer..

            – stack0114106
            Nov 22 '18 at 19:36



















          • This also works.. thanks for the answer..

            – stack0114106
            Nov 22 '18 at 19:36

















          This also works.. thanks for the answer..

          – stack0114106
          Nov 22 '18 at 19:36





          This also works.. thanks for the answer..

          – stack0114106
          Nov 22 '18 at 19:36











          1














          It can be done in a single pass if you're willing to use the log's wording for the Map keys.



          val Pattern = raw"(d+) records .*) ([^|]+)".r.unanchored

          log_text.split("n").flatMap{
          case Pattern(num, typ) => Some(typ -> num)
          case _ => None
          }.toMap
          //res0: immutable.Map[String,String] = Map(read -> 120, written -> 100, rejected -> 20)





          share|improve this answer
























          • Could you please add explanation on the unanchored?.. right now in travel will check tomorrow.. thanks for the answer..

            – stack0114106
            Nov 22 '18 at 19:55











          • btw.. why flatMap after the split? Will not just map() do the work?..

            – stack0114106
            Nov 22 '18 at 19:57











          • unanchored: Regex patterns in Scala are, by default, "anchored" to the start/end of the string, meaning, "This pattern describes the entire string from beginning to end." "unanchored", on the other hand, means, "This pattern describes some part of the string, which might, or might not, include the start and/or end."

            – jwvh
            Nov 22 '18 at 21:09











          • flatMap: Notice that I'm returning an Option (Some or None) from the map operation. If I had used map() the return type would be Array[Option[(String,String)]], which can't be turned into a Map. You can use .flatten to flatten a collection of Option[X] elements into a collection of just [X] elements, and all the None values will disappear. flatMap() is the combination of map(...).flatten.

            – jwvh
            Nov 22 '18 at 21:18


















          1














          It can be done in a single pass if you're willing to use the log's wording for the Map keys.



          val Pattern = raw"(d+) records .*) ([^|]+)".r.unanchored

          log_text.split("n").flatMap{
          case Pattern(num, typ) => Some(typ -> num)
          case _ => None
          }.toMap
          //res0: immutable.Map[String,String] = Map(read -> 120, written -> 100, rejected -> 20)





          share|improve this answer
























          • Could you please add explanation on the unanchored?.. right now in travel will check tomorrow.. thanks for the answer..

            – stack0114106
            Nov 22 '18 at 19:55











          • btw.. why flatMap after the split? Will not just map() do the work?..

            – stack0114106
            Nov 22 '18 at 19:57











          • unanchored: Regex patterns in Scala are, by default, "anchored" to the start/end of the string, meaning, "This pattern describes the entire string from beginning to end." "unanchored", on the other hand, means, "This pattern describes some part of the string, which might, or might not, include the start and/or end."

            – jwvh
            Nov 22 '18 at 21:09











          • flatMap: Notice that I'm returning an Option (Some or None) from the map operation. If I had used map() the return type would be Array[Option[(String,String)]], which can't be turned into a Map. You can use .flatten to flatten a collection of Option[X] elements into a collection of just [X] elements, and all the None values will disappear. flatMap() is the combination of map(...).flatten.

            – jwvh
            Nov 22 '18 at 21:18
















          1












          1








          1







          It can be done in a single pass if you're willing to use the log's wording for the Map keys.



          val Pattern = raw"(d+) records .*) ([^|]+)".r.unanchored

          log_text.split("n").flatMap{
          case Pattern(num, typ) => Some(typ -> num)
          case _ => None
          }.toMap
          //res0: immutable.Map[String,String] = Map(read -> 120, written -> 100, rejected -> 20)





          share|improve this answer













          It can be done in a single pass if you're willing to use the log's wording for the Map keys.



          val Pattern = raw"(d+) records .*) ([^|]+)".r.unanchored

          log_text.split("n").flatMap{
          case Pattern(num, typ) => Some(typ -> num)
          case _ => None
          }.toMap
          //res0: immutable.Map[String,String] = Map(read -> 120, written -> 100, rejected -> 20)






          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 22 '18 at 19:43









          jwvhjwvh

          26.4k52140




          26.4k52140













          • Could you please add explanation on the unanchored?.. right now in travel will check tomorrow.. thanks for the answer..

            – stack0114106
            Nov 22 '18 at 19:55











          • btw.. why flatMap after the split? Will not just map() do the work?..

            – stack0114106
            Nov 22 '18 at 19:57











          • unanchored: Regex patterns in Scala are, by default, "anchored" to the start/end of the string, meaning, "This pattern describes the entire string from beginning to end." "unanchored", on the other hand, means, "This pattern describes some part of the string, which might, or might not, include the start and/or end."

            – jwvh
            Nov 22 '18 at 21:09











          • flatMap: Notice that I'm returning an Option (Some or None) from the map operation. If I had used map() the return type would be Array[Option[(String,String)]], which can't be turned into a Map. You can use .flatten to flatten a collection of Option[X] elements into a collection of just [X] elements, and all the None values will disappear. flatMap() is the combination of map(...).flatten.

            – jwvh
            Nov 22 '18 at 21:18





















          • Could you please add explanation on the unanchored?.. right now in travel will check tomorrow.. thanks for the answer..

            – stack0114106
            Nov 22 '18 at 19:55











          • btw.. why flatMap after the split? Will not just map() do the work?..

            – stack0114106
            Nov 22 '18 at 19:57











          • unanchored: Regex patterns in Scala are, by default, "anchored" to the start/end of the string, meaning, "This pattern describes the entire string from beginning to end." "unanchored", on the other hand, means, "This pattern describes some part of the string, which might, or might not, include the start and/or end."

            – jwvh
            Nov 22 '18 at 21:09











          • flatMap: Notice that I'm returning an Option (Some or None) from the map operation. If I had used map() the return type would be Array[Option[(String,String)]], which can't be turned into a Map. You can use .flatten to flatten a collection of Option[X] elements into a collection of just [X] elements, and all the None values will disappear. flatMap() is the combination of map(...).flatten.

            – jwvh
            Nov 22 '18 at 21:18



















          Could you please add explanation on the unanchored?.. right now in travel will check tomorrow.. thanks for the answer..

          – stack0114106
          Nov 22 '18 at 19:55





          Could you please add explanation on the unanchored?.. right now in travel will check tomorrow.. thanks for the answer..

          – stack0114106
          Nov 22 '18 at 19:55













          btw.. why flatMap after the split? Will not just map() do the work?..

          – stack0114106
          Nov 22 '18 at 19:57





          btw.. why flatMap after the split? Will not just map() do the work?..

          – stack0114106
          Nov 22 '18 at 19:57













          unanchored: Regex patterns in Scala are, by default, "anchored" to the start/end of the string, meaning, "This pattern describes the entire string from beginning to end." "unanchored", on the other hand, means, "This pattern describes some part of the string, which might, or might not, include the start and/or end."

          – jwvh
          Nov 22 '18 at 21:09





          unanchored: Regex patterns in Scala are, by default, "anchored" to the start/end of the string, meaning, "This pattern describes the entire string from beginning to end." "unanchored", on the other hand, means, "This pattern describes some part of the string, which might, or might not, include the start and/or end."

          – jwvh
          Nov 22 '18 at 21:09













          flatMap: Notice that I'm returning an Option (Some or None) from the map operation. If I had used map() the return type would be Array[Option[(String,String)]], which can't be turned into a Map. You can use .flatten to flatten a collection of Option[X] elements into a collection of just [X] elements, and all the None values will disappear. flatMap() is the combination of map(...).flatten.

          – jwvh
          Nov 22 '18 at 21:18







          flatMap: Notice that I'm returning an Option (Some or None) from the map operation. If I had used map() the return type would be Array[Option[(String,String)]], which can't be turned into a Map. You can use .flatten to flatten a collection of Option[X] elements into a collection of just [X] elements, and all the None values will disappear. flatMap() is the combination of map(...).flatten.

          – jwvh
          Nov 22 '18 at 21:18




















          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%2f53432057%2fscala-getting-read-write-and-reject-records-with-simplified-regex%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

          Create new schema in PostgreSQL using DBeaver

          Deepest pit of an array with Javascript: test on Codility

          Costa Masnaga