我一直在尝试更多地了解 Rust 的函数式语言特性,所以我尝试采用这个函数:
fn minimum_length(s: String) -> i32 {
if s.len() <= 1 {
return s.len() as i32;
}
let mut len_after_deleting_similar_ends = s.len();
let x = len_after_deleting_similar_ends / 2;
for (first_char, last_char) in zip(s.chars().take(x), s.chars().rev().take(x)) {
if first_char == last_char {
len_after_deleting_similar_ends -= 2
} else {
return len_after_deleting_similar_ends as i32
}
};
len_after_deleting_similar_ends as i32
}
并重写它以使用
fold
方法而不是循环,目前我的代码是:
fn minimum_length_fold(s: String) -> i32 {
if s.len() <= 1 {
return s.len() as i32;
}
let len_after_deleting_similar_ends = zip(s.chars().take(s.len() / 2), s.chars().rev().take(s.len() / 2))
.fold(s.len(), |acc, (first_char, last_char)| {
println!("{first_char} {last_char} {acc}");
if first_char == last_char {
acc - 2
} else {
return acc;
}
});
len_after_deleting_similar_ends as i32
}
但是,任何会导致第一个函数提前返回的情况(最后一对字母的提前返回除外)都会给出不正确的结果。这是因为
return
返回到 fold
,而不是返回到 minimum_length_fold
的调用者,因此功能与省略 return
时相同。
如何更改此设置,以便一对不匹配的字母导致提前返回或某种类似有效的解决方案?
我的测试是:
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_1() {
assert_eq!(minimum_length(String::from("ca")), 2)
}
#[test]
fn test_2() {
assert_eq!(minimum_length(String::from("cabaabac")), 0);
}
#[test]
fn test_3() {
assert_eq!(minimum_length(String::from("caaaabac")), 4);
}
}
minimum_length
将通过所有三个,而minimum_length_fold
将失败test_3
,因为它没有提前返回,并且由于索引3和索引4处的匹配'a'
,累加器目前已减少,它通过test_2
尽管缺乏早期返回,因为没有后续匹配的字母对,这会导致累加器减少,因此尽管逻辑有缺陷,但答案是正确的。
我猜测实际要求的是如何使用迭代器来做到这一点。这是一种不使用折叠的方法(使用计数代替):
fn minimum_length(s: &str) -> usize {
s.len() - 2 * s.chars().zip(s.chars().rev()).take_while(|(a,b)|a==b).take(s.len()/2).count()
}
这可能与第一个解决方案一样快。
需要考虑的一件事是如何处理例如“a”。正如您编写的函数一样,它应该返回 1,但是字符串的两边是相同的,所以也许应该删除 'a',并且函数返回 0。