2017-04-07 29 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