简体   繁体   English

在Swift数组中查找唯一值

[英]Find unique values in a Swift Array

I am building a project that tells me the unique words in a piece of text. 我正在建立一个项目,告诉我一段文字中的独特单词。

I have my orginal string scriptTextView which I have added each word into the array scriptEachWordInArray 我有我的原始字符串scriptTextView ,我已将每个单词添加到数组scriptEachWordInArray中

I would now like to create an array called scriptUniqueWords which only includes words that appear once (in other words are unique) in scriptEachWordInArray 我现在想创建一个名为scriptUniqueWords的数组,它只包含在scriptEachWordInArray中出现一次(换句话说是唯一的)的单词。

So I'd like my scriptUniqueWords array to equal = ["Silent","Holy"] as a result. 所以我希望我的scriptUniqueWords数组等于= [“Silent”,“Holy”]作为结果。

I don't want to create an array without duplicates but an array that has only values that appeared once in the first place. 我不想创建一个没有重复项的数组,而是一个只有第一个出现一次值的数组。

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])")}

}

Swift 迅速

lets try It. 试试吧吧。

let array = ["1", "1", "2", "2", "3", "3"]
let unique = Array(Set(array))
// ["1", "2", "3"]

You can use NSCountedSet 您可以使用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: $0) == 1 }.flatMap { $0 as? String }

Now singleOccurrencies contains ["holy", "silent"] 现在singleOccurrencies包含["holy", "silent"]

Filtering out unique words without preserving order 过滤掉独特的单词而不保留顺序

As another alternative to NSCountedSet , you could use a dictionary to count the the number of occurrences of each word, and filter out those that only occur once: 作为NSCountedSet另一种替代NSCountedSet ,您可以使用字典来计算每个单词的出现次数,并过滤掉仅出现一次的单词:

let scriptEachWordInArray = ["Silent", "night", "Holy", "night"]

var freqs: [String: Int] = [:]
scriptEachWordInArray.forEach { freqs[$0] = (freqs[$0] ?? 0) + 1 }

let scriptUniqueWords = freqs.flatMap { $0.1 == 1 ? $0.0 : nil }
print(scriptUniqueWords) // ["Holy", "Silent"]

This solution, however (as well as the one using NSCountedSet ), will not preserve the order of the original array, since a dictionary as well as NSCountedSet is an unordered collection. 但是,此解决方案(以及使用NSCountedSet解决方案)不会保留原始数组的顺序,因为字典以及NSCountedSet是无序集合。


Filtering out unique words while preserving order 在保留订单的同时过滤掉独特的单词

If you'd like to preserve the order from the original array (removing element which appear more than once), you could count the frequencies of each word, but store it in a (String, Int) tuple array rather than a dictionary. 如果您想保留原始数组中的顺序(删除多次出现的元素),您可以计算每个单词的频率,但将其存储在(String, Int)元组数组而不是字典中。

Making use of the Collection extension from this Q&A 利用此问答中的Collection扩展

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[$0] {
                frequencies[idx].1 += 1
            }
            else {
                seen[$0] = frequencies.count
                frequencies.append(($0, 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[$0].1 += 1 } ?? {
                seen[elem] = frequencies.count
                return frequencies.append((elem, 1))
            }()
        }
        return frequencies
    }
}

... you may filter out the unique words of your array (while preserving order) as ...你可以过滤掉你的数组中的唯一单词(同时保留顺序)

let scriptUniqueWords = scriptEachWordInArray.frequencies
    .flatMap { $0.1 == 1 ? $0.0 : nil }

print(scriptUniqueWords) // ["Silent", "Holy"]

您可以过滤数组中已包含的值:

let newArray = array.filter { !array.contains($0) }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM