问题:如何判断一个字符串儿是否包含另一个字符串儿?
其实,字符串儿String里面本身就包含一个contains()方法,它可以在一定程度上判断一个字符串儿里面是否包含另一个字符串儿。但是,它比较傻,所能做的工作有限,比如说:
"Hello, July".contains("July") // 其返回值为true
"Hello, July".contains("july") // 其返回值应该为true,但实际却返回false
contains()方法是严格区分大小写的,而这种严格显然是与我们的要求不符。对于我们的题目来说,不管它是大写还是小写,只要是包含该字符串儿,它就符合题目的要求。所以,我们需要另外想办法对这种情况进行处理。为此,可以考虑给String写一个扩展:
extension String {
// 判断一个字符串儿是否包含另一个字符串儿,并且不用区分大小写
func fuzzyContains(_ string: String) -> Bool {
return self.uppercased().range(of: string.uppercased()) != nil
}
}
我来解释一下上面的代码。首先,self.uppercased()和string.uppercased()分别将两个字符串儿转换成大写字符。以上面的”Hello,July”和“July”或者“july”为例,self.uppercased()会将”Hello,July”中所有的字符全部转换成大写字符,而string.uppercased()则会将fuzzyContains(_ : )方法中的参数,也就是“July”或者“july”中所有的字符全部转换成大写字符。之所以要做这种转换,就是为了解决上面contains()方法不能正确处理大小写的情况。其次,range(of: ),这个方法就厉害了,它主要是返回一个字符串儿在另一个字符串儿中的位置,其结果为可选类型。如果我们调用range(of: ),所得到的结果为nil,那就说明子字符串儿不包含在我们检查的字符串儿中。如果相反,那就说明字字符串儿包含在待检查的字符串儿中:
上面的方法已经可以解决我们的问题了,但是不够简洁。还有一种方法,它可以将转换字符大、小写和判断是否包含子字符串儿合并到一起:
extension String {
func fuzzy1Contains(_ string: String) -> Bool {
return range(of: string, options: .caseInsensitive) != nil
}
}
"Hello, July".fuzzy1Contains("July") // 其返回值为true
"Hello, July".fuzzy1Contains("july") // 其返回值应该为true,实际返回结果也为true
extension String {
func fuzzy2Contains(_ string: String) -> Bool {
return range(of: string, options: .caseInsensitive, range: nil, locale: nil) != nil
}
}
"Hello, July".fuzzy2Contains("July") // 其返回值为true
"Hello, July".fuzzy2Contains("july") // 其返回值应该为true,实际返回结果也为true
也就是说,不必显式的进行字符串儿大、小写的转换,在使用range(of: )这个方法时,多传递一个参数caseInsensitive。它的作用就是告诉编译器,不用严格区分字符大小写。