在 Swift 数组中查找唯一值
Find unique values in a Swift Array
我正在构建一个项目,它告诉我一段文本中的独特单词。
我有我的原始字符串 scriptTextView,我已将每个单词添加到数组中 scriptEachWordInArray
我现在想创建一个名为 scriptUniqueWords 的数组,它只包含在 scriptEachWordInArray[=27= 中出现一次(换句话说是唯一的)的单词]
所以我希望我的 scriptUniqueWords 数组结果等于 = ["Silent","Holy"]。
我不想创建一个没有重复项的数组,而是一个只包含最初出现一次的值的数组。
var scriptTextView = "Silent Night Holy Night"
var scriptEachWordInArray = ["Silent", "night", "Holy", "night"]
var scriptUniqueWords = [String]()
for i in 0..<scriptEachWordInArray.count {
if scriptTextView.components(separatedBy: "\(scriptEachWordInArray[i]) ").count == 1 {
scriptUniqueWords.append(scriptEachWordInArray[i])
print("Unique word \(scriptEachWordInArray[i])")}
}
您可以使用NSCountedSet
let text = "Silent Night Holy Night"
let words = text.lowercased().components(separatedBy: " ")
let countedSet = NSCountedSet(array: words)
let singleOccurrencies = countedSet.filter { countedSet.count(for: [=10=]) == 1 }.flatMap { [=10=] as? String }
现在 singleOccurrencies
包含 ["holy", "silent"]
在不保留顺序的情况下过滤掉唯一的单词
作为NSCountedSet
的另一种替代方法,您可以使用字典来计算每个单词出现的次数,并过滤掉只出现一次的单词:
let scriptEachWordInArray = ["Silent", "night", "Holy", "night"]
var freqs: [String: Int] = [:]
scriptEachWordInArray.forEach { freqs[[=10=]] = (freqs[[=10=]] ?? 0) + 1 }
let scriptUniqueWords = freqs.flatMap { [=10=].1 == 1 ? [=10=].0 : nil }
print(scriptUniqueWords) // ["Holy", "Silent"]
但是,此解决方案(以及使用 NSCountedSet
的解决方案)不会保留原始数组的顺序,因为字典和 NSCountedSet
一样都是无序集合。
在保留顺序的同时过滤掉不重复的词
如果您想保留原始数组的顺序(删除出现不止一次的元素),您可以计算每个单词的频率,但将其存储在 (String, Int)
元组数组中比字典。
利用 Collection
extension from this Q&A
extension Collection where Iterator.Element: Hashable {
var frequencies: [(Iterator.Element, Int)] {
var seen: [Iterator.Element: Int] = [:]
var frequencies: [(Iterator.Element, Int)] = []
forEach {
if let idx = seen[[=11=]] {
frequencies[idx].1 += 1
}
else {
seen[[=11=]] = frequencies.count
frequencies.append(([=11=], 1))
}
}
return frequencies
}
}
// or, briefer but worse at showing intent
extension Collection where Iterator.Element: Hashable {
var frequencies: [(Iterator.Element, Int)] {
var seen: [Iterator.Element: Int] = [:]
var frequencies: [(Iterator.Element, Int)] = []
for elem in self {
seen[elem].map { frequencies[[=11=]].1 += 1 } ?? {
seen[elem] = frequencies.count
return frequencies.append((elem, 1))
}()
}
return frequencies
}
}
...您可以过滤掉数组中的唯一单词(同时保留顺序)如
let scriptUniqueWords = scriptEachWordInArray.frequencies
.flatMap { [=12=].1 == 1 ? [=12=].0 : nil }
print(scriptUniqueWords) // ["Silent", "Holy"]
您可以过滤数组中已包含的值:
let newArray = array.filter { !array.contains([=10=]) }
Swift
让我们试试。
let array = ["1", "1", "2", "2", "3", "3"]
let unique = Array(Set(array))
// ["1", "2", "3"]
我正在构建一个项目,它告诉我一段文本中的独特单词。
我有我的原始字符串 scriptTextView,我已将每个单词添加到数组中 scriptEachWordInArray
我现在想创建一个名为 scriptUniqueWords 的数组,它只包含在 scriptEachWordInArray[=27= 中出现一次(换句话说是唯一的)的单词]
所以我希望我的 scriptUniqueWords 数组结果等于 = ["Silent","Holy"]。
我不想创建一个没有重复项的数组,而是一个只包含最初出现一次的值的数组。
var scriptTextView = "Silent Night Holy Night"
var scriptEachWordInArray = ["Silent", "night", "Holy", "night"]
var scriptUniqueWords = [String]()
for i in 0..<scriptEachWordInArray.count {
if scriptTextView.components(separatedBy: "\(scriptEachWordInArray[i]) ").count == 1 {
scriptUniqueWords.append(scriptEachWordInArray[i])
print("Unique word \(scriptEachWordInArray[i])")}
}
您可以使用NSCountedSet
let text = "Silent Night Holy Night"
let words = text.lowercased().components(separatedBy: " ")
let countedSet = NSCountedSet(array: words)
let singleOccurrencies = countedSet.filter { countedSet.count(for: [=10=]) == 1 }.flatMap { [=10=] as? String }
现在 singleOccurrencies
包含 ["holy", "silent"]
在不保留顺序的情况下过滤掉唯一的单词
作为NSCountedSet
的另一种替代方法,您可以使用字典来计算每个单词出现的次数,并过滤掉只出现一次的单词:
let scriptEachWordInArray = ["Silent", "night", "Holy", "night"]
var freqs: [String: Int] = [:]
scriptEachWordInArray.forEach { freqs[[=10=]] = (freqs[[=10=]] ?? 0) + 1 }
let scriptUniqueWords = freqs.flatMap { [=10=].1 == 1 ? [=10=].0 : nil }
print(scriptUniqueWords) // ["Holy", "Silent"]
但是,此解决方案(以及使用 NSCountedSet
的解决方案)不会保留原始数组的顺序,因为字典和 NSCountedSet
一样都是无序集合。
在保留顺序的同时过滤掉不重复的词
如果您想保留原始数组的顺序(删除出现不止一次的元素),您可以计算每个单词的频率,但将其存储在 (String, Int)
元组数组中比字典。
利用 Collection
extension from this Q&A
extension Collection where Iterator.Element: Hashable {
var frequencies: [(Iterator.Element, Int)] {
var seen: [Iterator.Element: Int] = [:]
var frequencies: [(Iterator.Element, Int)] = []
forEach {
if let idx = seen[[=11=]] {
frequencies[idx].1 += 1
}
else {
seen[[=11=]] = frequencies.count
frequencies.append(([=11=], 1))
}
}
return frequencies
}
}
// or, briefer but worse at showing intent
extension Collection where Iterator.Element: Hashable {
var frequencies: [(Iterator.Element, Int)] {
var seen: [Iterator.Element: Int] = [:]
var frequencies: [(Iterator.Element, Int)] = []
for elem in self {
seen[elem].map { frequencies[[=11=]].1 += 1 } ?? {
seen[elem] = frequencies.count
return frequencies.append((elem, 1))
}()
}
return frequencies
}
}
...您可以过滤掉数组中的唯一单词(同时保留顺序)如
let scriptUniqueWords = scriptEachWordInArray.frequencies
.flatMap { [=12=].1 == 1 ? [=12=].0 : nil }
print(scriptUniqueWords) // ["Silent", "Holy"]
您可以过滤数组中已包含的值:
let newArray = array.filter { !array.contains([=10=]) }
Swift
让我们试试。
let array = ["1", "1", "2", "2", "3", "3"]
let unique = Array(Set(array))
// ["1", "2", "3"]