Разбиение целого числа на отдельные цифры
Я пишу функцию, которая требует, чтобы отдельные цифры большего целого числа выполняли операции.
Я попробовал следующее:
// I can safely unwrap because I know the chars of the string are going to be valid
let digits = num.to_string().chars().map(|d| d.to_digit(10).unwrap());
Но проверка заимствования говорит, что строка живет недостаточно долго.
Работает следующее:
let temp = num.to_string();
let digits = temp.chars().map(|d| d.to_digit(10).unwrap());
Но это почему-то выглядит еще более надуманным.
Есть ли лучший и, возможно, более естественный способ сделать это?1 ответ:
Но проверка заимствования говорит, что строка живет недостаточно долго.Это потому, что он не. Вы не используете итератор, поэтому Тип
digits
-std::iter::Map<std::str::Chars<'_>, <closure>>
То есть еще не оцененный итератор, содержащий ссылки на выделенную строку (Безымянное время жизни
'_
вChars
). Однако, поскольку у этой строки нет владельца,она отбрасывается в конце инструкции; перед использованием итератора.Итак, ура для ржавчины, это предотвратило используйте-после-свободного бага!
Использование итератора "решит" проблему, так как ссылки на выделенную строку не будут пытаться жить дольше, чем выделенная строка; все они заканчиваются в конце утверждения:
let digits: Vec<_> = num.to_string().chars().map(|d| d.to_digit(10).unwrap()).collect();
Что касается альтернативного решения, есть математический способ , украденный из вопроса C++ :
Тем не менее, вы можете добавить всю логику особых случаев для отрицательных чисел, и тестирование не будет плохой идеей.fn x(n: usize) -> Vec<usize> { fn x_inner(n: usize, xs: &mut Vec<usize>) { if n >= 10 { x_inner(n / 10, xs); } xs.push(n % 10); } let mut xs = Vec::new(); x_inner(n, &mut xs); xs } fn main() { let num = 42; let digits: Vec<_> = num.to_string().chars().map(|d| d.to_digit(10).unwrap()).collect(); println!("{:?}", digits); let digits = x(42); println!("{:?}", digits); }
Вы могли бы также нужна версия итератора fancy-pants:
struct Digits { n: usize, divisor: usize, } impl Digits { fn new(n: usize) -> Self { let mut divisor = 1; while n >= divisor * 10 { divisor *= 10; } Digits { n: n, divisor: divisor, } } } impl Iterator for Digits { type Item = usize; fn next(&mut self) -> Option<Self::Item> { if self.divisor == 0 { None } else { let v = Some(self.n / self.divisor); self.n %= self.divisor; self.divisor /= 10; v } } } fn main() { let digits: Vec<_> = Digits::new(42).collect(); println!("{:?}", digits); }