2017-04-07 49 views
1

鉴于串s后的字符串下一个字符边界指标,这是该指数i字符开始的地方:查找字符

let s = "abc 好 def"; 
let i = 4; 

那是什么字后获得该指数的最佳途径,使我可以切分字符串并获得abc 好?在代码:

let end = find_end(s, i); 
assert_eq!("abc 好", &s[0..end]); 

(注意,+ 1不起作用,因为它假定字符是只有一个字节长。)

目前,我有以下几点:

fn find_end(s: &str, i: usize) -> usize { 
    i + s[i..].chars().next().unwrap().len_utf8() 
} 

但我想知道我是否错过了一些东西,还有更好的方法吗?

回答

1

您可以使用char_indices来获取下一个索引,而不是在字符上使用len_utf8,尽管对于最后一个字符有特殊情况。

我会用方便的str::is_char_boundary()方法。下面是使用一个实现:

fn find_end(s: &str, i: usize) -> usize { 
    assert!(i < s.len()); 
    let mut end = i+1; 
    while !s.is_char_boundary(end) { 
     end += 1; 
    } 
    end 
} 

Playground link

通常我会做的情况下,这样的函数返回Option<usize>这就是所谓的用在s末的索引,但现在我只是断言。

在很多情况下,不是明确调用find_end,而是使用char_indices进行迭代,它可以为每个索引提供字符;尽管如果你想知道当前角色的结尾,它有点烦人。

+0

感谢您的回答!我没有在这个问题中加入它,但我在某个时候也有'is_char_boundary'。有了'char_indices',如果你停在一个字符并想获得下一个索引,你可以使用'i + c.len_utf8()',这也是一个好主意! – robinst

0

为了补充@ ChrisEmerson的回答,这就是人们如何实现find_end来搜索角色首次出现的结尾。 Playground

fn find_end<'s>(s: &'s str, p: char) -> Option<usize> { 
    let mut indices = s.char_indices(); 
    let mut found = false; 
    for (_, v) in &mut indices { 
     if v == p { 
      found = true; 
      break; 
     } 
    } 
    if found { 
     Some(indices.next() 
        .map_or_else(|| s.len(), |(i, _)| i)) 
    } else { 
     None 
    } 
} 

虽然避免了字节边界环,它仍然不是很优雅。理想情况下,遍历直到符合谓词的迭代器方法可以简化这个过程。

+0

我有点惊讶,似乎没有'next_char_boundary'方法! –

+0

非常感谢!使用'next()'的缺点是只有在当前字符之后有另一个字符时才起作用。 – robinst

+0

@ChrisEmerson是的,'next_char_boundary'方法是完美的。 – robinst