从折叠内提前返回

问题描述 投票:0回答:1

我一直在尝试更多地了解 Rust 的函数式语言特性,所以我尝试采用这个函数:

  1. 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
方法而不是循环,目前我的代码是:

  1. 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
尽管缺乏早期返回,因为没有后续匹配的字母对,这会导致累加器减少,因此尽管逻辑有缺陷,但答案是正确的。

rust fold
1个回答
0
投票

我猜测实际要求的是如何使用迭代器来做到这一点。这是一种不使用折叠的方法(使用计数代替):

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。

© www.soinside.com 2019 - 2024. All rights reserved.