Find a line starting with a given index

What is the correct way to search for a substring if I need to start at a non-0?

I have this code:

fn SplitFile(reader: BufReader<File>) { for line in reader.lines() { let mut l = line.unwrap(); // l contains "06:31:53.012 index0:2015-01-06 00:00:13.084 ... 

I need to find the third one : and analyze the date behind it. I still don’t know how to do this, because find has no parameters, such as begin - see https://doc.rust-lang.org/std/string/struct.String.html#method.find .

(I know that I can use regex. I did this, but I would like to compare performance - can parsing manually be faster than using regex.)

+6
source share
3 answers

You are right, there is no trivial way to skip a few matches when searching for a string. You can do it manually.

 fn split_file(reader: BufReader<File>) { for line in reader.lines() { let mut l = &line.as_ref().unwrap()[..]; // get a slice for _ in 0..3 { if let Some(idx) = l.find(":") { l = &l[idx+1..] } else { panic!("the line didn't have enough colons"); // you probably shouldn't panic } } // l now contains the date ... 

Update:

As faiface points below , you can do it a little cleaner with splitn()

 fn split_file(reader: BufReader<File>) { for line in reader.lines() { let l = line.unwrap(); if let Some(datetime) = l.splitn(4, ':').last() { // datetime now contains the timestamp string ... } else { panic!("line doesn't contain a timestamp"); } } } 

You must raise your answer.

+4
source

In my opinion, there is a much simpler solution to this problem, namely the use of the .splitn() method. This method breaks a string according to a given pattern no more than n times. For instance:

 let s = "ab:bc:cd:de:ef".to_string(); println!("{:?}", s.splitn(3, ':').collect::<Vec<_>>()); // ^ prints ["ab", "bc", "cd:de:ef"] 

In your case, you need to break the string into 4 parts, separated by the ':' character, and take the fourth (with an index of 0):

 // assuming the line is correctly formatted let date = l.splitn(4, ':').nth(3).unwrap(); 

If you do not want to use a spread (the string may be formatted incorrectly):

 if let Some(date) = l.splitn(4, ':').nth(3) { // parse the date and time } 
+4
source

Only date, not time, right?

 let test: String = "06:31:53.012 index0:2015-01-06 00:00:13.084".into(); let maybe_date = test.split_whitespace() .skip(1) .next() .and_then(|substring| substring.split(":").skip(1).next()); assert_eq!(maybe_date, Some("2015-01-06")); 
+1
source

All Articles