Cleaned up "Extract phone numbers from text" example

This commit is contained in:
Michal Budzynski 2017-07-30 14:34:23 +02:00
parent afcc46e5fc
commit 412b70e7b3

View file

@ -652,41 +652,36 @@ fn main() {
<a name="ex-phone"></a> <a name="ex-phone"></a>
## Extract phone numbers from text ## Extract phone numbers from text
[![regex-badge]][regex] [![cat-text-processing-badge]][cat-text-processing]
Processes a string of text using [`Regex::captures_iter`] to capture multiple Processes a string of text using [`Regex::captures_iter`] to capture multiple
phone numbers. The example here is for US convention phone numbers. phone numbers. The example here is for US convention phone numbers.
```rust, no_run ```rust
# #[macro_use] # #[macro_use]
# extern crate error_chain; # extern crate error_chain;
extern crate regex; extern crate regex;
use regex::Regex; use regex::Regex;
use std::fmt; use std::fmt;
#
# error_chain!{ # error_chain!{
# foreign_links { # foreign_links {
# Regex(regex::Error); # Regex(regex::Error);
# Io(std::io::Error); # Io(std::io::Error);
# } # }
# } # }
#
#[derive(PartialEq, PartialOrd, Debug)] struct PhoneNumber<'a> {
struct PhoneNumber { area: &'a str,
area: &'static str, exchange: &'a str,
exchange: &'static str, subscriber: &'a str,
subscriber: &'static str,
} }
// Allows printing phone numbers based on country convention. // Allows printing phone numbers based on country convention.
impl fmt::Display for PhoneNumber { impl<'a> fmt::Display for PhoneNumber<'a> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!( write!(f, "1 ({}) {}-{}", self.area, self.exchange, self.subscriber)
f,
"1 ({}) {}-{}",
&self.area,
&self.exchange,
&self.subscriber
)
} }
} }
@ -697,56 +692,49 @@ fn run() -> Result<()> {
Alex 5553920011 Alex 5553920011
1 (800) 233-2010 1 (800) 233-2010
1.299.339.1020"; 1.299.339.1020";
let re = Regex::new( let re = Regex::new(
r"(?x) r#"(?x)
(?:\+?1)? # Country Code Optional (?:\+?1)? # Country Code Optional
[\s\.]? [\s\.]?
(([2-9]\d{2})|\(([2-9]\d{2})\)) # Area Code (([2-9]\d{2})|\(([2-9]\d{2})\)) # Area Code
[\s\.\-]? [\s\.\-]?
([2-9]\d{2}) # Exchange Code ([2-9]\d{2}) # Exchange Code
[\s\.\-]? [\s\.\-]?
(\d{4}) #Subscriber Number", (\d{4}) # Subscriber Number"#,
)?; )?;
let mut phone_numbers = re.captures_iter(phone_text).map(|cap| {
// Area code populates either capture group 2 or 3. Group 1 contains optional paranthesis. let phone_numbers = re.captures_iter(phone_text).filter_map(|cap| {
PhoneNumber { // Area code populates either capture group 2 or 3.
area: if cap.get(2) == None { // Group 1 contains optional parenthesis.
cap.get(3).map_or("", |m| m.as_str()) let groups = (cap.get(2).or(cap.get(3)), cap.get(4), cap.get(5));
} else { match groups {
cap.get(2).map_or("", |m| m.as_str()) (Some(area), Some(ext), Some(sub)) => Some(PhoneNumber {
}, area: area.as_str(),
exchange: cap.get(4).map_or("", |m| m.as_str()), exchange: ext.as_str(),
subscriber: cap.get(5).map_or("", |m| m.as_str()), subscriber: sub.as_str(),
}),
_ => None,
} }
}); assert_eq!( });
phone_numbers.next().map(|m| m.to_string()),
Some("1 (505) 881-9292".to_owned())
);
assert_eq!( assert_eq!(
phone_numbers.next().map(|m| m.to_string()), phone_numbers.map(|m| m.to_string()).collect::<Vec<_>>(),
Some("1 (505) 778-2212".to_owned()) vec![
); "1 (505) 881-9292",
assert_eq!( "1 (505) 778-2212",
phone_numbers.next().map(|m| m.to_string()), "1 (505) 881-9297",
Some("1 (505) 881-9297".to_owned()) "1 (202) 991-9534",
); "1 (555) 392-0011",
assert_eq!( "1 (800) 233-2010",
phone_numbers.next().map(|m| m.to_string()), "1 (299) 339-1020",
Some("1 (202) 991-9534".to_owned()) ]
);
assert_eq!(
phone_numbers.next().map(|m| m.to_string()),
Some("1 (555) 392-0011".to_owned())
);
assert_eq!(
phone_numbers.next().map(|m| m.to_string()),
Some("1 (800) 233-2010".to_owned())
); );
Ok(()) Ok(())
} }
# #
# quick_main!(run); # quick_main!(run);
``` ```
[ex-sha-digest]: #ex-sha-digest [ex-sha-digest]: #ex-sha-digest