如何使用递归定义检查Swift中的回文

问题描述 投票:3回答:9

我喜欢Swift中的许多功能,但使用操作字符串仍然是一个很大的痛苦。

func checkPalindrome(word: String) -> Bool {
    print(word)
    if word == "" {
        return true
    } else {
        if word.characters.first == word.characters.last {
            return checkPalindrome(word.substringWithRange(word.startIndex.successor() ..< word.endIndex.predecessor()))
        } else {
            return false
        }
    }
}

只要字符串的长度为奇数,此代码就会失败。当然我可以这样做,所以块的第一行将是if word.characters.count < 2,但在Swift有一种方法可以获得子串并轻松检查吗?

更新我喜欢很多建议,但我想最初的问题可能会误导一点,因为这是一个关于String的问题而不是为函数获得正确的结果。

例如,在Python中,checkPalindrome(word [1:-1])可以很好地用于递归定义,而Swift代码则不那么优雅,因为它需要其他的花里胡哨。

swift recursion palindrome
9个回答
3
投票

有时使用前端进行递归可以简化生活。我有时会在最方便使用的参数不是我想要的用户界面时执行此操作。

以下是否满足您的需求?

func checkPalindrome(str: String) -> Bool {
  func recursiveTest(var charSet: String.CharacterView) -> Bool {
    if charSet.count < 2 {
      return true
    } else {
      if charSet.popFirst() != charSet.popLast() {
        return false
      } else {
        return recursiveTest(charSet)
      }
    }
  }
  return recursiveTest(str.characters)
}

0
投票

将字符串转换为数组。执行循环时获取第一个索引并与最后一个索引进行比较。

func palindrome(string: String)-> Bool{
    let char = Array(string)
    for i in 0..<char.count / 2 {
        if char[i] != char[char.count - 1 - i] {
            return false
        }
    }
    return true
}

-1
投票
func checkPalindrome(_ inputString: String) -> Bool {
    if inputString.count % 2 == 0 {
        return false
    } else if inputString.count == 1 {
        return true
    } else {
        var stringCount = inputString.count
        while stringCount != 1 {
            if inputString.first == inputString.last {
                stringCount -= 2
            } else {
                continue
            }
        }
        if stringCount == 1 {
            return true
        } else {
            return false
        }
    }
}

3
投票
func isPalindrome(myString:String) -> Bool {
    let reverseString = String(myString.characters.reversed())
    if(myString != "" && myString == reverseString) {
        return true
    } else {
        return false
    }
}

print(isPalindrome("madam"))

3
投票
if word == String(word.reversed())
{
    return true
}
return false

2
投票

只是在if中添加更多条件

        func checkPalindrome(word: String) -> Bool {
        print(word)
    if (word == "" || word.characters.count == 1){
            return true

        }
    else {
            if word.characters.first == word.characters.last {
                return checkPalindrome(word.substringWithRange(word.startIndex.successor() ..< word.endIndex.predecessor()))
            } else {
                return false
            }
        }
    }

2
投票
extension String {
    var lettersOnly: String {
        return componentsSeparatedByCharactersInSet(NSCharacterSet.letterCharacterSet().invertedSet).joinWithSeparator("")
    }

    var isPalindrome: Bool {
        return String(characters.reverse()).lettersOnly.lowercaseString == lettersOnly.lowercaseString
    }
}

"Dammit I'm Mad".isPalindrome    // true

"Socorram-me subi no onibus em marrocos".isPalindrome   // true

你也可以将你的字符串分解为一个字符数组并迭代它们,直到它的一半与它的对应物逐一比较:

func checkPalindrome(word: String) -> Bool {
    let chars = Array(word.lettersOnly.lowercaseString.characters)
    for index in  0..<chars.count/2 {
        if chars[index] != chars[chars.count.predecessor() - index] {
            return false
        }
    }
    return true
}

并且修复范围问题的递归版本无法使用endIndex <startIndex形成范围:

func checkPalindrome<T: StringProtocol>(_ word: T) -> Bool where T.Index == String.Index {
    let word = word.lowercased()
        .components(separatedBy: .punctuationCharacters).joined()
        .components(separatedBy: .whitespacesAndNewlines).joined()
    if word == "" || word.count == 1 {
        return true
    } else {
        if word.first == word.last {
            let start = word.index(word.startIndex,offsetBy: 1, limitedBy: word.endIndex) ?? word.startIndex
            let end = word.index(word.endIndex,offsetBy: -1, limitedBy: word.startIndex) ?? word.endIndex
            return checkPalindrome(word[start..<end])
        } else {
            return false
        }
    }
}
checkPalindrome("Dammit I'm Mad")

1
投票

我想如果你像这样扩展String,那么它会让你的生活变得更轻松:

extension String {
    var length: Int { return characters.count }

    subscript(index: Int) -> Character {
        return self[startIndex.advancedBy(index)]
    }

    subscript(range: Range<Int>) -> String {
        return self[Range<Index>(start: startIndex.advancedBy(range.startIndex), end: startIndex.advancedBy(range.endIndex))]
    }
}

有了它,您可以将功能更改为:

func checkPalindrome(word: String) -> Bool {
    if word.length < 2 {
        return true
    } 

    if word.characters.first != word.characters.last {
        return false
    }

    return checkPalindrome(word[1..<word.length - 1])
}

快速测试:

print(checkPalindrome("aba")) // Prints "true"
print(checkPalindrome("abc")) // Prints "false"

0
投票

并没有真正想到这一点,但我想我想出了一个非常酷的扩展,并认为我会分享。

extension String {
    var subString: (Int?) -> (Int?) -> String {
        return { (start) in
            { (end) in
                let startIndex = start ?? 0 < 0 ? self.endIndex.advancedBy(start!) : self.startIndex.advancedBy(start ?? 0)
                let endIndex = end ?? self.characters.count < 0 ? self.endIndex.advancedBy(end!) : self.startIndex.advancedBy(end ?? self.characters.count)

                return startIndex > endIndex ? "" : self.substringWithRange(startIndex ..< endIndex)
            }
        }
    }
}


let test = ["Eye", "Pop", "Noon", "Level", "Radar", "Kayak", "Rotator", "Redivider", "Detartrated", "Tattarrattat", "Aibohphobia", "Eve", "Bob", "Otto", "Anna", "Hannah", "Evil olive", "Mirror rim", "Stack cats", "Doom mood", "Rise to vote sir", "Step on no pets", "Never odd or even", "A nut for a jar of tuna", "No lemon, no melon", "Some men interpret nine memos", "Gateman sees name, garageman sees nametag"]

func checkPalindrome(word: String) -> Bool {
    if word.isEmpty { return true }
    else {
        if word.subString(nil)(1) == word.subString(-1)(nil) {
            return checkPalindrome(word.subString(1)(-1))
        } else {
            return false
        }
    }
}

for item in test.map({ $0.lowercaseString.stringByReplacingOccurrencesOfString(",", withString: "").stringByReplacingOccurrencesOfString(" ", withString: "") }) {
    if !checkPalindrome(item) {
        print(item)
    }
}

0
投票

我使用下面的扩展来查找数字是Palindrome还是Not。

extension String {
    var isPalindrome: Bool {
        return self == String(self.reversed())
    } 
 }

0
投票
extension String {

    func trimmingFirstAndLastCharacters() -> String {
        guard let startIndex = index(self.startIndex, offsetBy: 1, limitedBy: self.endIndex) else {
            return self
        }

        guard let endIndex = index(self.endIndex, offsetBy: -1, limitedBy: self.startIndex) else {
            return self
        }

        guard endIndex >= startIndex else {
            return self
        }

        return String(self[startIndex..<endIndex])
    }

    var isPalindrome: Bool {
        guard count > 1 else {
            return true
        }

        return first == last && trimmingFirstAndLastCharacters().isPalindrome
    }
}

我们首先声明一个从字符串中删除第一个和最后一个字符的函数。

接下来,我们声明一个计算机属性,它将包含检查字符串是否为回文的实际递归代码。

如果字符串的大小小于或等于1,我们立即返回true(由一个字符组成的字符串,如"a"或空字符串""被认为是回文),否则我们检查字符串的第一个和最后一个字符是否相同,我们递归调用isPalindrome在当前字符串中删除了第一个和最后一个字符。

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