What is the correct way how to find a substring if I need to start not from 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 third :
and parse the date behind it. Still no idea how to do it, because find
doesn't have any param like begin
- see https://doc.rust-lang.org/std/string/struct.String.html#method.find.
(I know I can use regex. I have it done, but I'd like to compare the performance - whether parsing by hand might the quicker than using regex.)
This process is referred to as indexing. Strings are ordered sequences of character data, 00:15 and the individual characters of a string can be accessed directly using that numerical index.
The indexOf() method returns the position of the first occurrence of specified character(s) in a string. Tip: Use the lastIndexOf method to return the position of the last occurrence of specified character(s) in a string.
Strings are zero-indexed: The index of a string's first character is 0 , and the index of a string's last character is the length of the string minus 1.
To find the index of first occurrence of a substring in a string you can use String. indexOf() function. A string, say str2 , can occur in another string, say str1 , n number of times. There could be a requirement in your Java application, that you have to find the position of the first occurrence of str2 in str1 .
There is a lot simpler solution to this problem in my opinion, and that is to use a .splitn()
method. This method splits a string by a given pattern at most n times. For example:
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 split the line into 4 parts separated by ':'
and take the 4th one (indexed from 0):
// assuming the line is correctly formatted
let date = l.splitn(4, ':').nth(3).unwrap();
If you don't want to use unwrap (the line might not be correctly formatted):
if let Some(date) = l.splitn(4, ':').nth(3) {
// parse the date and time
}
You are right, there doesn't appear to be any trivial way of skipping several matches when searching a string. You can do it by hand though.
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 out below, you can do this a bit 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 should go upvote his answer.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With