[英]How can I convert a string with integers to array with integers in java?
[英]How can I convert a string of numbers to an array or vector of integers in Rust?
我在 STDIN 上寫了一串數字(例如4 10 30 232312
),我想讀取它並轉換為整數數組(或向量),但我找不到正確的方法。 到目前為止,我有:
use std::io;
fn main() {
let mut reader = io::stdin();
let numbers = reader.read_line().unwrap();
}
你可以這樣做:
use std::io::{self, BufRead}; // (a)
fn main() {
let reader = io::stdin();
let numbers: Vec<i32> =
reader.lock() // (0)
.lines().next().unwrap().unwrap() // (1)
.split(' ').map(|s| s.trim()) // (2)
.filter(|s| !s.is_empty()) // (3)
.map(|s| s.parse().unwrap()) // (4)
.collect(); // (5)
println!("{:?}", numbers);
}
首先,我們鎖定標准輸入,讓您可以將標准輸入用作緩沖讀取器。 默認情況下,Rust 中的 stdin 是無緩沖的; 您需要調用lock()
方法來獲取它的緩沖版本,但是這個緩沖版本是程序中所有線程的唯一一個,因此對它的訪問應該是同步的。
接下來,我們閱讀下一行(1); 我正在使用lines()
迭代器,其next()
方法返回Option<io::Result<String>>
,因此要僅獲取String
您需要unwrap()
兩次。
然后我們用空格分割它並從額外的空白(2)中修剪結果塊,刪除修剪后留下的空塊(3),將字符串轉換為i32
s(4)並將結果收集到向量(5)。
我們還需要導入std::io::BufRead
trait (a) 以使用lines()
方法。
如果您事先知道您的輸入不會在數字之間包含多個空格,則可以省略步驟 (3) 並將trim()
調用從 (2) 移至 (1):
let numbers: Vec<i32> =
reader.lock()
.lines().next().unwrap().unwrap()
.trim().split(' ')
.map(|s| s.parse().unwrap())
.collect();
Rust 還提供了一種將字符串拆分為一系列以空格分隔的單詞的方法,稱為split_whitespace()
:
let numbers: Vec<i32> =
reader.read_line().unwrap().as_slice()
.split_whitespace()
.map(|s| s.parse().unwrap())
.collect()
split_whitespace()
實際上只是split()
和filter()
,就像我原來的例子一樣。 它使用split()
函數參數來檢查不同種類的空格,而不僅僅是空格字符。
在 Rust 1.5.x 上,一個可行的解決方案是:
fn main() {
let mut numbers = String::new();
io::stdin()
.read_line(&mut numbers)
.ok()
.expect("read error");
let numbers: Vec<i32> = numbers
.split_whitespace()
.map(|s| s.parse().expect("parse error"))
.collect();
for num in numbers {
println!("{}", num);
}
}
更安全的版本。 這個會跳過失敗的解析,這樣失敗的解包就不會恐慌。 使用read_line
讀取單行。
let mut buf = String::new();
// use read_line for reading single line
std::io::stdin().read_to_string(&mut buf).expect("");
// this one skips failed parses so that failed unwrap doesn't panic
let v: Vec<i32> = buf
.split_whitespace() // split string into words by whitespace
.filter_map(|w| w.parse().ok()) // calling ok() turns Result to Option so that filter_map can discard None values
.collect(); // collect items into Vector. This determined by type annotation.
您甚至可以像這樣閱讀 Vector of Vectors。
let stdin = io::stdin();
let locked = stdin.lock();
let vv: Vec<Vec<i32>> = locked.lines()
.filter_map(
|l| l.ok().map(
|s| s.split_whitespace()
.filter_map(|word| word.parse().ok())
.collect()))
.collect();
上面的一個適用於像這樣的輸入
2 424 -42 124
42 242 23 22 241
24 12 3 232 445
然后把它們變成
[[2, 424, -42, 124],
[42, 242, 23, 22, 241],
[24, 12, 3, 232, 445]]
filter_map
接受一個返回Option<T>
並過濾掉所有None
的閉包。
ok()
將Result<R,E>
為Option<R>
以便在這種情況下可以過濾錯誤。
Dulguun Otgon
更安全版本只是跳過所有錯誤。 如果您不想跳過錯誤,請考慮使用下一種方法。
fn parse_to_vec<'a, T, It>(it: It) -> Result<Vec<T>, <T as FromStr>::Err>
where
T: FromStr,
It: Iterator<Item = &'a str>,
{
it.map(|v| v.parse::<T>()).fold(Ok(Vec::new()), |vals, v| {
vals.and_then(|mut vals| {
v.and_then(|v| {
vals.push(v);
Ok(vals)
})
})
})
}
在使用它時,您可以按照通常的恐慌方式與expect
let numbers = parse_to_vec::<i32, _>(data_str.trim().split(" "))
.expect("can't parse data");
或更聰明的方式轉換為結果
let numbers = parse_to_vec::<i32, _>(data_str.trim().split(" "))
.map_err(|e| format!("can't parse data: {:?}", e))?;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.