scala getting read,write and reject records with simplified regex
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
add a comment |
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
add a comment |
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
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
scala scala-collections
asked Nov 22 '18 at 13:27
stack0114106stack0114106
3,1642417
3,1642417
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
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)
Great answer!..you simplified greatly..
– stack0114106
Nov 22 '18 at 19:35
add a comment |
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
This also works.. thanks for the answer..
– stack0114106
Nov 22 '18 at 19:36
add a comment |
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)
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 anOption
(Some
orNone
) from the map operation. If I had usedmap()
the return type would beArray[Option[(String,String)]]
, which can't be turned into aMap
. You can use.flatten
to flatten a collection ofOption[X]
elements into a collection of just[X]
elements, and all theNone
values will disappear.flatMap()
is the combination ofmap(...).flatten
.
– jwvh
Nov 22 '18 at 21:18
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
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)
Great answer!..you simplified greatly..
– stack0114106
Nov 22 '18 at 19:35
add a comment |
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)
Great answer!..you simplified greatly..
– stack0114106
Nov 22 '18 at 19:35
add a comment |
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)
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)
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
add a comment |
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
add a comment |
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
This also works.. thanks for the answer..
– stack0114106
Nov 22 '18 at 19:36
add a comment |
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
This also works.. thanks for the answer..
– stack0114106
Nov 22 '18 at 19:36
add a comment |
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
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
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
add a comment |
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
add a comment |
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)
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 anOption
(Some
orNone
) from the map operation. If I had usedmap()
the return type would beArray[Option[(String,String)]]
, which can't be turned into aMap
. You can use.flatten
to flatten a collection ofOption[X]
elements into a collection of just[X]
elements, and all theNone
values will disappear.flatMap()
is the combination ofmap(...).flatten
.
– jwvh
Nov 22 '18 at 21:18
add a comment |
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)
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 anOption
(Some
orNone
) from the map operation. If I had usedmap()
the return type would beArray[Option[(String,String)]]
, which can't be turned into aMap
. You can use.flatten
to flatten a collection ofOption[X]
elements into a collection of just[X]
elements, and all theNone
values will disappear.flatMap()
is the combination ofmap(...).flatten
.
– jwvh
Nov 22 '18 at 21:18
add a comment |
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)
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)
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 anOption
(Some
orNone
) from the map operation. If I had usedmap()
the return type would beArray[Option[(String,String)]]
, which can't be turned into aMap
. You can use.flatten
to flatten a collection ofOption[X]
elements into a collection of just[X]
elements, and all theNone
values will disappear.flatMap()
is the combination ofmap(...).flatten
.
– jwvh
Nov 22 '18 at 21:18
add a comment |
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 anOption
(Some
orNone
) from the map operation. If I had usedmap()
the return type would beArray[Option[(String,String)]]
, which can't be turned into aMap
. You can use.flatten
to flatten a collection ofOption[X]
elements into a collection of just[X]
elements, and all theNone
values will disappear.flatMap()
is the combination ofmap(...).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
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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