查找从给定索引开始的字符串

时间:2015-07-07 21:38:27

标签: rust

如果我不需要从0开始,如何找到子串的正确方法是什么?

我有这段代码:

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
    ...

我需要找到第三个:并解析它背后的日期。仍然不知道怎么做,因为find没有像begin那样的任何参数 - 请参阅https://doc.rust-lang.org/std/string/struct.String.html#method.find

我知道我可以使用正则表达式。我已经完成了,但我想比较性能 - 手动解析是否比使用正则表达式更快。<​​/ em>)

3 个答案:

答案 0 :(得分:5)

在我看来,这个问题有一个更简单的解决方案,那就是使用.splitn()方法。此方法最多n次按给定模式拆分字符串。例如:

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

在您的情况下,您需要将行拆分为由':'分隔的4个部分,并取第4个部分(从0开始索引):

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

如果您不想使用展开(行可能没有正确格式化):

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

答案 1 :(得分:4)

你是对的,搜索字符串时似乎没有任何跳过几个匹配的简单方法。你可以手工完成。

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
        ...

<强>更新

faiface指出below时,您可以使用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");
        }
    }
}

你应该回答他的答案。

答案 2 :(得分:1)

只是日期,而不是时间,对吗?

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"));