Rustで文字列を分割するにはどうすればよいですか?


143

ドキュメントからは、それは明確ではありません。Javaでは、次のsplitようにメソッドを使用できます。

"some string 123 ffd".split("123");


@bowベクトルではなく文字列配列にする方法はありますか?
グレッグ

私はそれを行う方法を少なくとも直接知りません。おそらく、手動で反復処理Splitして配列に設定する必要があります。もちろん、これは、配列は固定サイズであり、事前に配列を定義しておく必要があるため、各分割の項目数は同じでなければならないことを意味します。これは単にを作成するよりも難しいかもしれないと思いVecます。

回答:


158

使用する split()

let mut split = "some string 123 ffd".split("123");

これはイテレータを提供します。これをループするかcollect()、ベクトルに入れます。

for s in split {
    println!("{}", s)
}
let vec = split.collect::<Vec<&str>>();
// OR
let vec: Vec<&str> = split.collect();

15
書くこともできます.collect::<Vec<_>>()
Chris Morgan

結果の長さを取得するにはどうすればよいlet splitですか?split.len()存在しません。
アレックス

5
@AlexanderSupertrampの使用.count()len()消費する必要がなく、正確なサイズを知っているイテレータ専用であり、イテレータをcount()消費します。
Manishearth 2014年

error: cannot borrow immutable local variable mutable`としてsplit`
アレックス

@AlexanderSupertramp let mut split、ごめんなさい。
Manishearth 2014

53

3つの簡単な方法があります。

  1. することにより、セパレータ

    s.split("separator")  |  s.split('/')  |  s.split(char::is_numeric)
  2. 空白

    s.split_whitespace()
  3. ことで改行

    s.lines()

各種類の結果はイテレータです:

let text = "foo\r\nbar\n\nbaz\n";
let mut lines = text.lines();

assert_eq!(Some("foo"), lines.next());
assert_eq!(Some("bar"), lines.next());
assert_eq!(Some(""), lines.next());
assert_eq!(Some("baz"), lines.next());

assert_eq!(None, lines.next());

29

splitstructにStringは特別なメソッドがあります。

fn split<'a, P>(&'a self, pat: P) -> Split<'a, P> where P: Pattern<'a>

文字で分割:

let v: Vec<&str> = "Mary had a little lamb".split(' ').collect();
assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]);

文字列で分割:

let v: Vec<&str> = "lion::tiger::leopard".split("::").collect();
assert_eq!(v, ["lion", "tiger", "leopard"]);

閉鎖によって分割:

let v: Vec<&str> = "abc1def2ghi".split(|c: char| c.is_numeric()).collect();
assert_eq!(v, ["abc", "def", "ghi"]);

14

split返しIteratorあなたに変換することができ、Vec使用してはcollectsplit_line.collect::<Vec<_>>()Vec直接返す代わりにイテレータを通過することにはいくつかの利点があります:

  • split怠惰です。これは、必要になるまで実際には行を分割しないことを意味します。そうすれば、最初のいくつかの値だけが必要なsplit_line.take(2).collect::<Vec<_>>()場合、または整数に変換できる最初の値のみが必要な場合でも、文字列全体を分割するのに時間を浪費しません。split_line.filter_map(|x| x.parse::<i32>().ok()).next()。この最後の例では、「23.0」の処理に時間を費やすことはありませんが、「1」が見つかるとすぐに処理を停止します。
  • split結果を保存する方法を想定していません。を使用できVecますがFromIterator<&str>LinkedListやなどの実装するものVecDeque、またはを実装するカスタムタイプを使用することもできますFromIterator<&str>

1
任意のアイデアは、あなたの詳細な回答いただきありがとうございます、なぜlet x = line.unwrap().split(",").collect::<Vec<_>>();それが二つの別々の行に分割されていない限り動作しませんlet x = line.unwrap();let x = x.split(",").collect::<Vec<_>>();?エラーメッセージは言う:temporary value created here ^ temporary value dropped here while still borrowed
グレッグ

ただし、私が使用する場合は期待どおりに機能しますlet x = line.as_ref().unwrap().split(",").collect::<Vec<_>>();
Greg

6

またあります split_whitespace()

fn main() {
    let words: Vec<&str> = "   foo   bar\t\nbaz   ".split_whitespace().collect();
    println!("{:?}", words);
    // ["foo", "bar", "baz"] 
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.