gpt4 book ai didi

ios - Swift 字谜检查器

转载 作者:搜寻专家 更新时间:2023-10-30 22:19:34 24 4
gpt4 key购买 nike

我正在尝试为 swift 构建一个字谜检查器。这是我的代码。如果您不知道,字谜检查器会检查两个字符串中是否包含相同的字符,但顺序无关紧要。

func checkForAnagram(#firstString: String, #secondString: String) -> Bool {
var firstStringArray: [Character] = []
var secondStringArray: [Character] = []
/* if case matters delete the next four lines
and make sure your variables are not constants */
var first = firstString
var second = secondString
first = first.lowercaseString
second = second.lowercaseString
for charactersOne in first {
firstStringArray += [charactersOne]
}
for charactersTwo in second {
secondStringArray += [charactersTwo]
}
if firstStringArray.count != secondStringArray.count {
return false
} else {
for elements in firstStringArray {
if secondStringArray.contains(elements){
return true
} else {
return false
}
}

}
}


var a = "Hello"
var b = "oellh"
var c = "World"
checkForAnagram(firstString: a, secondString: b)

我收到一条错误消息。

'[Character]' does not have a member 'contains'

最佳答案

公认的答案简洁而优雅,但与其他解决方案相比效率非常低。

我现在将提议并讨论几个变体的 anagram 检查器的实现。为了衡量性能,我将使用不同的变体从 50,000 多个单词的数组中找出给定单词的变位词。

// Variant 1: Sorting of Character
// Measured time: 30.46 s
func anagramCheck1(a: String, b: String) -> Bool {
return a.characters.sorted() == b.characters.sorted()
}

这基本上是已接受答案的解决方案,用 Swift 3 语法编写。它非常慢,因为 Swift 的 String 与 NSString 不同,它是基于 Character 的,它可以正确处理 Unicode 字符。

一个更有效的解决方案是利用 NSCountedSet 类,它允许我们将字符串表示为一组字符,每个字符都有自己的计数。如果两个字符串映射到相同的 NSCountedSet,则它们是变位词。注意:检查字符串长度作为先决条件使实现总是更高效。

// Variant 2: NSCountedSet of Character
// Measured time: 4.81 s
func anagramCheck2(a: String, b: String) -> Bool {
guard a.characters.count == b.characters.count else { return false }
let aSet = NSCountedSet()
let bSet = NSCountedSet()
for c in a.characters {
aSet.add(c)
}
for c in b.characters {
bSet.add(c)
}
return aSet == bSet
}

更好但不是特别好。在这里,“罪魁祸首”之一是使用原生的 Swift 字符类型(来自 Swift 的字符串)。回到良好的旧 Objective-C 类型(NSString 和 unichar)可以使事情更有效率。

// Variant 3: NSCountedSet of unichar
// Measured time: 1.31 s
func anagramCheck3(a: String, b: String) -> Bool {
let aString = a as NSString
let bString = b as NSString
let length = aString.length
guard length == bString.length else { return false }
let aSet = NSCountedSet()
let bSet = NSCountedSet()
for i in 0..<length {
aSet.add(aString.character(at: i))
bSet.add(bString.character(at: i))
}
return aSet == bSet
}

使用 NSCountedSet 没问题,但在我们比较两个 NSCountedSet 对象之前,我们要完全填充它们。一个有用的替代方法是只为两个字符串中的一个完全填充 NSCountedSet,然后,当我们为另一个字符串填充 NSCountedSet 时,如果另一个字符串包含在第一个字符串的 NSCountedSet 中找不到的字符,我们会提前失败字符串。

// Variant 4: NSCountedSet of unichar and early exit
// Measured time: 1.07 s
func anagramCheck4(a: String, b: String) -> Bool {
let aString = a as NSString
let bString = b as NSString
let length = aString.length
guard length == bString.length else { return false }
let aSet = NSCountedSet()
let bSet = NSCountedSet()
for i in 0..<length {
aSet.add(aString.character(at: i))
}
for i in 0..<length {
let c = bString.character(at: i)
if bSet.count(for: c) >= aSet.count(for: c) {
return false
}
bSet.add(c)
}
return true
}

这是我们将获得的最佳时机(使用 Swift)。但是,为了完整起见,让我讨论这种类型的另一种变体。

下一个替代方案利用 [unichar: Int] 类型的 Swift 字典来存储每个字符的重复次数,而不是 NSCountedSet。它比前两个变体稍慢,但我们可以稍后重用它以获得更快的实现。

// Variant 5: counting repetitions with [unichar:Int]
// Measured time: 1.36
func anagramCheck5(a: String, b: String) -> Bool {
let aString = a as NSString
let bString = b as NSString
let length = aString.length
guard length == bString.length else { return false }
var aDic = [unichar:Int]()
var bDic = [unichar:Int]()
for i in 0..<length {
let c = aString.character(at: i)
aDic[c] = (aDic[c] ?? 0) + 1
}
for i in 0..<length {
let c = bString.character(at: i)
let count = (bDic[c] ?? 0) + 1
if count > aDic[c] ?? 0 {
return false
}
bDic[c] = count
}
return true
}

请注意,使用 NSCountedSet 的 vanilla Objective-C 实现(对应于变体 3)比所有以前的版本都快得多。

// Variant 6: Objective-C and NSCountedSet
// Measured time: 0.65 s
- (BOOL)anagramChecker:(NSString *)a with:(NSString *)b {
if (a.length != b.length) {
return NO;
}
NSCountedSet *aSet = [[NSCountedSet alloc] init];
NSCountedSet *bSet = [[NSCountedSet alloc] init];
for (int i = 0; i < a.length; i++) {
[aSet addObject:@([a characterAtIndex:i])];
[bSet addObject:@([b characterAtIndex:i])];
}
return [aSet isEqual:bSet];
}

我们可以改进之前尝试的另一种方法是观察到,如果我们需要找到给定单词的变位词,我们不妨认为该单词是固定的,因此我们可以构建相应的结构(NSCountedSet, Dictionary, ...) 对于那个词只有一次。

// Finding all the anagrams of word in words
// Variant 7: counting repetitions with [unichar:Int]
// Measured time: 0.58 s
func anagrams(word: String, from words: [String]) -> [String] {
let anagrammedWord = word as NSString
let length = anagrammedWord.length
var aDic = [unichar:Int]()
for i in 0..<length {
let c = anagrammedWord.character(at: i)
aDic[c] = (aDic[c] ?? 0) + 1
}
let foundWords = words.filter {
let string = $0 as NSString
guard length == string.length else { return false }
var bDic = [unichar:Int]()
for i in 0..<length {
let c = string.character(at: i)
let count = (bDic[c] ?? 0) + 1
if count > aDic[c] ?? 0 {
return false
}
bDic[c] = count
}
return true
}
return foundWords
}

现在,在之前的变体中,我们使用 [unichar:Int] 字典进行计数。事实证明,这比使用 unichar 的 NSCountedSet 更有效,无论是提前退出(0.60 秒)还是不提前退出(0.87 秒)。

关于ios - Swift 字谜检查器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32209803/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com