如何迭代向后范围?

时间:2017-03-02 02:04:49

标签: iterator rust match

我正在尝试创建pub fn sing(start: i32, end: i32) -> String,该pub fn verse(num: i32) -> String会在startend之间的每个数字上重复调用pub fn verse(num: i32) -> String { match num { 0 => "No more bottles of beer on the wall, no more bottles of beer.\nGo to the store and buy some more, 99 bottles of beer on the wall.\n".to_string(), 1 => "1 bottle of beer on the wall, 1 bottle of beer.\nTake it down and pass it around, no more bottles of beer on the wall.\n".to_string(), 2 => "2 bottles of beer on the wall, 2 bottles of beer.\nTake one down and pass it around, 1 bottle of beer on the wall.\n".to_string(), num => format!("{0} bottles of beer on the wall, {0} bottles of beer.\nTake one down and pass it around, {1} bottles of beer on the wall.\n",num,(num-1)), } } pub fn sing(start: i32, end: i32) -> String { (start..end).fold(String::new(), |ans, x| ans+&verse(x)) } 的结果串联字符串。

我已经用Google搜索了答案,似乎Rust String concatenation回答了我的问题,如果我甚至在playground中编写代码就可以了,但是:

我的代码:

#[test]
fn test_song_8_6() {
    assert_eq!(beer::sing(8, 6), "8 bottles of beer on the wall, 8 bottles of beer.\nTake one down and pass it around, 7 bottles of beer on the wall.\n\n7 bottles of beer on the wall, 7 bottles of beer.\nTake one down and pass it around, 6 bottles of beer on the wall.\n\n6 bottles of beer on the wall, 6 bottles of beer.\nTake one down and pass it around, 5 bottles of beer on the wall.\n");
}

问题在于

beer::sing(8,6)

""返回 KeyPairGenerator kpGenerator = KeyPairGenerator.getInstance("RSA", "AndroidKeyStore"); AlgorithmParameterSpec spec = null; if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR1 && Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { spec = new KeyPairGeneratorSpec.Builder(ctx) .setAlias(mAlias) .setSubject(new X500Principal("CN=" + mAlias)) .setSerialNumber(BigInteger.valueOf(1337)) .setStartDate(start.getTime()) .setEndDate(end.getTime()) .build(); } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { spec = new KeyGenParameterSpec.Builder(mAlias, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT) .setDigests(KeyProperties.DIGEST_SHA256, KeyProperties.DIGEST_SHA512) .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1) .build(); kpGenerator.initialize(spec); KeyPair kp = kpGenerator.generateKeyPair(); 时失败。

1 个答案:

答案 0 :(得分:7)

您的问题与字符串连接无关。它与8..6是一个空迭代器的事实有关,因为范围只向前迭代。因为8 >= 6,迭代器会在第一次调用None时产生next

fn main() {
    for i in 8..6 {
        println!("{}", i); // never reached
    }
}

可以通过交换startend并调用rev()来向后迭代来解决此问题。

fn main() {
    for i in (6..8).rev() {
        println!("{}", i);
    }
}

然而,还有另一个问题。在start..end范围内,start包含但end是独占的。例如,上面的代码打印76; 8未打印。见How do I include the end value in a range?

总而言之,sing应如下所示:

pub fn sing(start: i32, end: i32) -> String {
    (end..=start)
        .rev()
        .fold(String::new(), |ans, x| ans + &verse(x))
}

注意:您的测试仍然失败,因为它预计每个节目之间有两个换行符,但您的代码只生成一个。我会把这个留给你修理。