反转字符串的一部分
Reverse part of a String
我正在完成 codefights 练习,结果得到了一些混乱的代码,在 Python 中,是相对简单的字符串切片和连接:
s = "the quick (brown (fox) jumps) over"
(f, t) = (18, 21)
ss = s[:f] + s[t-1:f-1:-1] + s[t:]
生锈:
let s = String::from("the quick (brown (fox) jumps) over");
let sc: Vec<_> = s.chars().collect();
let (f, t) = (18, 21); // result of searching through sc
let mut new_s: Vec<_> = sc[..f].into_iter().collect();
new_s.extend(&sc[f..t].into_iter().rev().collect::<Vec<_>>());
new_s.extend(&sc[t..].into_iter().collect::<Vec<_>>());
let mut ss = String::with_capacity(new_s.len());
for c in new_s.iter() {ss.push(**c);}
主要是通过添加一些东西来修复编译错误,我最终遇到了似乎无法降低的复杂性。 'proper' 在 Rust 中执行此操作的方法是什么?
我没有使用 replace()
做类似答案的事情,因为这是搜索字符串并反转匹配括号内部分的问题的简化示例。
假设子串只出现一次(或者当您想要反转所有子串时):
fn main() {
let s = String::from("the quick (brown (fox) jumps) over");
let to_rev = &"fox";
let ss = s.replace(to_rev, &to_rev.chars().rev().collect::<String>());
println!("{}", ss); // the quick (brown (xof) jumps) over
}
这应该只分配两次给你的 5,我不确定是否有办法摆脱中间分配:
let ss: String = s.chars()
.take(f)
.chain(s.chars().skip(f).take(t-f).collect::<Vec<_>>().into_iter().rev())
.chain(s.chars().skip(t))
.collect();
请注意,UTF-8 字符串操作比 Python 代码似乎暗示的要复杂得多。例如,在存在组合字符 (playground).
的情况下,这两种解决方案都无法达到您的预期。
下面去掉中间分配:
let ss: String = s.chars()
.take(f)
.chain(s.chars().rev().skip(s.chars().count()-t).take(t-f))
.chain(s.chars().skip(t))
.collect();
对于 Unicode,我们需要使用 s.chars().count()
而不是 s.len()
,因为 s.len()
是代码单位,我们需要代码点的长度。
这更容易理解,但仅适用于 ASCII,或者如果 f
和 t
是代码单元中的索引:
let ss: String = s[..f].chars()
.chain(s[f..t].chars().rev())
.chain(s[t..].chars())
.collect();
我正在完成 codefights 练习,结果得到了一些混乱的代码,在 Python 中,是相对简单的字符串切片和连接:
s = "the quick (brown (fox) jumps) over"
(f, t) = (18, 21)
ss = s[:f] + s[t-1:f-1:-1] + s[t:]
生锈:
let s = String::from("the quick (brown (fox) jumps) over");
let sc: Vec<_> = s.chars().collect();
let (f, t) = (18, 21); // result of searching through sc
let mut new_s: Vec<_> = sc[..f].into_iter().collect();
new_s.extend(&sc[f..t].into_iter().rev().collect::<Vec<_>>());
new_s.extend(&sc[t..].into_iter().collect::<Vec<_>>());
let mut ss = String::with_capacity(new_s.len());
for c in new_s.iter() {ss.push(**c);}
主要是通过添加一些东西来修复编译错误,我最终遇到了似乎无法降低的复杂性。 'proper' 在 Rust 中执行此操作的方法是什么?
我没有使用 replace()
做类似答案的事情,因为这是搜索字符串并反转匹配括号内部分的问题的简化示例。
假设子串只出现一次(或者当您想要反转所有子串时):
fn main() {
let s = String::from("the quick (brown (fox) jumps) over");
let to_rev = &"fox";
let ss = s.replace(to_rev, &to_rev.chars().rev().collect::<String>());
println!("{}", ss); // the quick (brown (xof) jumps) over
}
这应该只分配两次给你的 5,我不确定是否有办法摆脱中间分配:
let ss: String = s.chars()
.take(f)
.chain(s.chars().skip(f).take(t-f).collect::<Vec<_>>().into_iter().rev())
.chain(s.chars().skip(t))
.collect();
请注意,UTF-8 字符串操作比 Python 代码似乎暗示的要复杂得多。例如,在存在组合字符 (playground).
的情况下,这两种解决方案都无法达到您的预期。下面去掉中间分配:
let ss: String = s.chars()
.take(f)
.chain(s.chars().rev().skip(s.chars().count()-t).take(t-f))
.chain(s.chars().skip(t))
.collect();
对于 Unicode,我们需要使用 s.chars().count()
而不是 s.len()
,因为 s.len()
是代码单位,我们需要代码点的长度。
这更容易理解,但仅适用于 ASCII,或者如果 f
和 t
是代码单元中的索引:
let ss: String = s[..f].chars()
.chain(s[f..t].chars().rev())
.chain(s[t..].chars())
.collect();