我正在尝试为swift构建一个anagram检查器。这是我的代码。如果您不知道anagram检查器检查两个字符串是否包含相同的字符,但顺序无关紧要。
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'
答案 0 :(得分:16)
你应该试试
System.out.println(map.containsValue("mark"));
答案 1 :(得分:16)
接受的答案是紧凑而优雅,但与其他解决方案相比效率非常低。
我现在将提出并讨论一些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语法编写的接受答案的解决方案。它非常慢,因为与NSString不同,Swift的String基于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 Character类型(来自Swift的String)。回到旧的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 Dictionary来存储每个字符的重复次数,而不是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
}
请注意,与Variant 3相对应的使用NSCountedSet的vanilla Objective-C实现比以前的所有版本都要快得多。
// 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,字典,...)只有一次这个词。
// 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]字典。这证明比使用NSCountedSet的unichar更有效,无论是提前退出(0.60秒)还是没有(0.87秒)。
答案 2 :(得分:1)
// This answer also would work
// Convert your parameters on Array, then sorted them and compare them
func ana(str1: String, str2: String)->Bool{
let a = Array(str1)
let b = Array(str2)
if a.sorted() == b.sorted() {
return true
}
return false
}
答案 3 :(得分:1)
不要忘记空格
func isAnagram(_ stringOne: String, stringTwo: String) -> Bool {
return stringOne.lowercased().sorted().filter { $0 != " "} stringTwo.lowercased().sorted().filter { $0 != " "}
}
答案 4 :(得分:0)
// Make sure name your variables correctly so you won't confuse
// Mutate the constants parameter, lowercase to handle capital letters and the sorted them to compare both. Finally check is there are equal return true or false.
func anagram(str1: String, srt2: String)->Bool{
let string1 = str1.lowercased().sorted()
let string2 = srt2.lowercased().sorted()
if string1 == string2 {
return true
}
return false
}
答案 5 :(得分:0)
我们可以使用字典来构造一个新的数据结构容器。然后按字符串的键/字符比较该值。
func anagram(str1: String, str2 : String) -> Bool {
var dict1 = [Character: Int](), dict2 = [Character: Int]()
str1.forEach { (char) in
if dict1[char] != nil {
dict1[char]! += 1
} else {
dict1[char] = 1
}
}
str2.forEach { (char) in
if dict2[char] != nil {
dict2[char]! += 1
} else {
dict2[char] = 1
}
}
return dict1 == dict2 ? true : false
}
// input -> "anna", "aann"
// The count will look like:
// ["a": 2, "n": 2] & ["a": 2, "n": 2]
// then return true
答案 6 :(得分:0)
func checkAnagrams(str1: String, str2: String) -> Bool {
guard str1.count == str2.count else { return false }
var dictionary = Dictionary<Character, Int>()
for index in 0..<str1.count {
let value1 = str1[str1.index(str1.startIndex, offsetBy: index)]
let value2 = str2[str2.index(str2.startIndex, offsetBy: index)]
dictionary[value1] = (dictionary[value1] ?? 0) + 1
dictionary[value2] = (dictionary[value2] ?? 0) - 1
}
return !dictionary.contains(where: {(_, value) in
return value != 0
})
}
时间复杂度-O(n)
答案 7 :(得分:0)
func isAnagram(word1: String, word2: String) -> Bool {
let set1 = Set(word1)
let set2 = Set(word2)
return set1 == set2
}
or
func isAnagram(word1: String,word2: String) -> Bool {
return word1.lowercased().sorted() == word2.lowercased().sorted()
}
答案 8 :(得分:0)
Swift 4.1函数将为您提供3个关于Anagram的问题答案:-
1。输入字符串(a,b)是Anagram吗? //布尔
2。如果不是Anagram,那么计数的数量需要更改字符串(a,b)中的字符以使它们成为anagram? // Int
3。如果不是Anagram,则需要更改字符串(a,b)中的字符列表以使它们成为anagram? // [字符]
步骤1:-复制并粘贴以下内容到所需的班级:-
//MARK:- Anagram checker
func anagramChecker(a:String,b:String) -> (Bool,Int,[Character]) {
var aCharacters = Array(a)
var bCharacters = Array(b)
var count = 0
var isAnagram = true
var replacementRequiredWords:[Character] = [Character]()
if aCharacters.count == bCharacters.count {
let listA = aCharacters.filter { !bCharacters.contains($0) }
for i in 0 ..< listA.count {
if !replacementRequiredWords.contains(listA[i]) {
count = count + 1
replacementRequiredWords.append(listA[i])
isAnagram = false
}
}
let listB = bCharacters.filter { !aCharacters.contains($0) }
for i in 0 ..< listB.count {
if !replacementRequiredWords.contains(listB[i]) {
count = count + 1
replacementRequiredWords.append(listB[i])
isAnagram = false
}
}
}else{
//cant be an anagram
count = -1
}
return (isAnagram,count,replacementRequiredWords)
}
第2步:-输入两个要测试的输入字符串
// Input Strings
var a = "aeb"
var b = "abs"
步骤3:-打印结果:-
print("isAnagram : \(isAnagram(a: a, b: b).0)")
print("number of count require to change strings in anagram : \(isAnagram(a: a, b: b).1)")//-1 will come in case of cant be a Anagram
print("list of Characters needs to be change : \(isAnagram(a: a, b: b).2)")
上述练习的结果:-
isAnagram : false
number of count require to change strings in anagram : 2
list of Characters needs to be change : ["e", "s"]
希望这个10分钟的练习将对我的Swift有所帮助 家族,轻松解决Anagram相关问题。 :)
答案 9 :(得分:0)
使用Swift中的inout方法检查两个字符串是否为字谜
func checkAnagramString(str1: inout String, str2: inout String)-> Bool{
var result:Bool = false
str1 = str1.lowercased().trimmingCharacters(in: .whitespace)
str2 = str2.lowercased().trimmingCharacters(in: .whitespaces)
if (str1.count != str2.count) {
return result
}
for c in str1 {
if str2.contains(c){
result = true
}
else{
result = false
return result
}
}
return result
}
调用函数以检查字符串是否为字谜
var str1 = "tommarvoloriddle"
var str2 = "iamlordvoldemort"
print(checkAnagramString(str1: &str1, str2: &str2)) //Output = true.
答案 10 :(得分:0)
我刚刚意识到在 Swift 5.X
中执行Anagram函数的另一种简便方法func checkForAnagram(firstString firstString: String, secondString: String) -> Bool {
return !firstString.isEmpty && firstString.sorted() == secondString.sorted()
}