Swift 배열에서 요소 발생 횟수를 계산하는 방법은 무엇입니까?
저는 이것의 몇 가지 예를 보았지만, 모든 예는 발생 횟수를 세고 싶은 요소를 아는 것에 의존하는 것처럼 보입니다.어레이가 동적으로 생성되므로 발생 횟수를 셀 요소를 알 수 없습니다(모든 요소의 발생 횟수를 세고 싶습니다).누가 조언해 줄 수 있습니까?
편집:
배열에 여러 개의 다른 문자열이 포함되어 있으므로 더 명확했어야 합니다(예:["FOO", "FOO", "BAR", "FOOBAR"]
푸, 바, 푸바가 무엇인지 미리 알지 못한 채 어떻게 발생 횟수를 셀 수 있습니까?
스위프트 3 및 스위프트 2:
유형의 사전을 사용할 수 있습니다.[String: Int]
당신의 각 항목에 대한 카운트를 쌓다[String]
:
let arr = ["FOO", "FOO", "BAR", "FOOBAR"]
var counts: [String: Int] = [:]
for item in arr {
counts[item] = (counts[item] ?? 0) + 1
}
print(counts) // "[BAR: 1, FOOBAR: 1, FOO: 2]"
for (key, value) in counts {
print("\(key) occurs \(value) time(s)")
}
출력:
BAR occurs 1 time(s)
FOOBAR occurs 1 time(s)
FOO occurs 2 time(s)
스위프트 4:
Swift 4는 (SE-0165) 사전 조회와 함께 기본값을 포함하는 기능을 도입했으며, 결과 값은 다음과 같은 작업을 통해 변형될 수 있습니다.+=
그리고.-=
그래서:
counts[item] = (counts[item] ?? 0) + 1
다음이 됩니다.
counts[item, default: 0] += 1
따라서 다음을 사용하여 하나의 간결한 줄에서 계수 작업을 쉽게 수행할 수 있습니다.forEach
:
let arr = ["FOO", "FOO", "BAR", "FOOBAR"]
var counts: [String: Int] = [:]
arr.forEach { counts[$0, default: 0] += 1 }
print(counts) // "["FOOBAR": 1, "FOO": 2, "BAR": 1]"
스위프트 4:reduce(into:_:)
Swift 4는 새로운 버전의reduce
를 사용하는inout
결과를 누적할 변수입니다.이를 사용하면 카운트가 실제로 단일 행으로 생성됩니다.
let arr = ["FOO", "FOO", "BAR", "FOOBAR"]
let counts = arr.reduce(into: [:]) { counts, word in counts[word, default: 0] += 1 }
print(counts) // ["BAR": 1, "FOOBAR": 1, "FOO": 2]
또는 기본 매개 변수 사용:
let counts = arr.reduce(into: [:]) { $0[$1, default: 0] += 1 }
마지막으로 이것을 의 확장으로 만들 수 있습니다.Sequence
어떤 경우에도 호출될 수 있도록.Sequence
재중Hashable
다음을 포함한 항목Array
,ArraySlice
,String
,그리고.String.SubSequence
:
extension Sequence where Element: Hashable {
var histogram: [Element: Int] {
return self.reduce(into: [:]) { counts, elem in counts[elem, default: 0] += 1 }
}
}
이 아이디어는 계산된 속성으로 바꿨지만 이 질문에서 차용한 것입니다.@LeoDabus의 확장 제안에 감사드립니다.Sequence
대신에Array
추가 유형을 선택합니다.
예:
print("abacab".histogram)
["a": 3, "b": 2, "c": 1]
print("Hello World!".suffix(6).histogram)
["l": 1, "!": 1, "d": 1, "o": 1, "W": 1, "r": 1]
print([1,2,3,2,1].histogram)
[2: 2, 3: 1, 1: 2]
print([1,2,3,2,1,2,1,3,4,5].prefix(8).histogram)
[1: 3, 2: 3, 3: 2]
print(stride(from: 1, through: 10, by: 2).histogram)
[1: 1, 3: 1, 5: 1, 7: 1, 9: 1]
array.filter{$0 == element}.count
Swift 5를 사용하면 필요에 따라 다음 7개의 Playground 샘플 코드 중 하나를 선택하여 배열에서 해시 가능한 항목의 발생 횟수를 계산할 수 있습니다.
#1. 사용하기Array
의reduce(into:_:)
그리고.Dictionary
의subscript(_:default:)
첨자
let array = [4, 23, 97, 97, 97, 23]
let dictionary = array.reduce(into: [:]) { counts, number in
counts[number, default: 0] += 1
}
print(dictionary) // [4: 1, 23: 2, 97: 3]
#2. 사용하기repeatElement(_:count:)
기능.zip(_:_:)
기능 및Dictionary
의init(_:uniquingKeysWith:)
이니셜라이저
let array = [4, 23, 97, 97, 97, 23]
let repeated = repeatElement(1, count: array.count)
//let repeated = Array(repeating: 1, count: array.count) // also works
let zipSequence = zip(array, repeated)
let dictionary = Dictionary(zipSequence, uniquingKeysWith: { (current, new) in
return current + new
})
//let dictionary = Dictionary(zipSequence, uniquingKeysWith: +) // also works
print(dictionary) // prints [4: 1, 23: 2, 97: 3]
#3. 사용하기Dictionary
의init(grouping:by:)
이니셜라이저 및mapValues(_:)
방법
let array = [4, 23, 97, 97, 97, 23]
let dictionary = Dictionary(grouping: array, by: { $0 })
let newDictionary = dictionary.mapValues { (value: [Int]) in
return value.count
}
print(newDictionary) // prints: [97: 3, 23: 2, 4: 1]
#4. 사용하기Dictionary
의init(grouping:by:)
이니셜라이저 및map(_:)
방법
let array = [4, 23, 97, 97, 97, 23]
let dictionary = Dictionary(grouping: array, by: { $0 })
let newArray = dictionary.map { (key: Int, value: [Int]) in
return (key, value.count)
}
print(newArray) // prints: [(4, 1), (23, 2), (97, 3)]
#5. 루프 및Dictionary
의subscript(_:)
첨자
extension Array where Element: Hashable {
func countForElements() -> [Element: Int] {
var counts = [Element: Int]()
for element in self {
counts[element] = (counts[element] ?? 0) + 1
}
return counts
}
}
let array = [4, 23, 97, 97, 97, 23]
print(array.countForElements()) // prints [4: 1, 23: 2, 97: 3]
#6. 사용하기NSCountedSet
그리고.NSEnumerator
의map(_:)
메소드(기초 필요)
import Foundation
extension Array where Element: Hashable {
func countForElements() -> [(Element, Int)] {
let countedSet = NSCountedSet(array: self)
let res = countedSet.objectEnumerator().map { (object: Any) -> (Element, Int) in
return (object as! Element, countedSet.count(for: object))
}
return res
}
}
let array = [4, 23, 97, 97, 97, 23]
print(array.countForElements()) // prints [(97, 3), (4, 1), (23, 2)]
#7. 사용하기NSCountedSet
그리고.AnyIterator
(기초 필요)
import Foundation
extension Array where Element: Hashable {
func counForElements() -> Array<(Element, Int)> {
let countedSet = NSCountedSet(array: self)
var countedSetIterator = countedSet.objectEnumerator().makeIterator()
let anyIterator = AnyIterator<(Element, Int)> {
guard let element = countedSetIterator.next() as? Element else { return nil }
return (element, countedSet.count(for: element))
}
return Array<(Element, Int)>(anyIterator)
}
}
let array = [4, 23, 97, 97, 97, 23]
print(array.counForElements()) // [(97, 3), (4, 1), (23, 2)]
학점:
나는 스위프트2에 oisdk의 답변을 업데이트했습니다.
2014년 4월 16일 이 코드를 Swift2.2로 업데이트했습니다.
2011년 10월 16일 Swift3로 업데이트됨
해시 가능:
extension Sequence where Self.Iterator.Element: Hashable {
private typealias Element = Self.Iterator.Element
func freq() -> [Element: Int] {
return reduce([:]) { (accu: [Element: Int], element) in
var accu = accu
accu[element] = accu[element]?.advanced(by: 1) ?? 1
return accu
}
}
}
동등한 것:
extension Sequence where Self.Iterator.Element: Equatable {
private typealias Element = Self.Iterator.Element
func freqTuple() -> [(element: Element, count: Int)] {
let empty: [(Element, Int)] = []
return reduce(empty) { (accu: [(Element, Int)], element) in
var accu = accu
for (index, value) in accu.enumerated() {
if value.0 == element {
accu[index].1 += 1
return accu
}
}
return accu + [(element, 1)]
}
}
}
사용.
let arr = ["a", "a", "a", "a", "b", "b", "c"]
print(arr.freq()) // ["b": 2, "a": 4, "c": 1]
print(arr.freqTuple()) // [("a", 4), ("b", 2), ("c", 1)]
for (k, v) in arr.freq() {
print("\(k) -> \(v) time(s)")
}
// b -> 2 time(s)
// a -> 4 time(s)
// c -> 1 time(s)
for (element, count) in arr.freqTuple() {
print("\(element) -> \(count) time(s)")
}
// a -> 4 time(s)
// b -> 2 time(s)
// c -> 1 time(s)
NScounted Set을 사용합니다.목표 C:
NSCountedSet* countedSet = [[NSCountedSet alloc] initWithArray:array];
for (NSString* string in countedSet)
NSLog (@"String %@ occurs %zd times", string, [countedSet countForObject:string]);
이것은 당신이 직접 Swift로 번역할 수 있다고 생각합니다.
어때요?
func freq<S: SequenceType where S.Generator.Element: Hashable>(seq: S) -> [S.Generator.Element:Int] {
return reduce(seq, [:]) {
(var accu: [S.Generator.Element:Int], element) in
accu[element] = accu[element]?.successor() ?? 1
return accu
}
}
freq(["FOO", "FOO", "BAR", "FOOBAR"]) // ["BAR": 1, "FOOBAR": 1, "FOO": 2]
일반적이기 때문에 해시 가능한 한 요소가 무엇이든 사용할 수 있습니다.
freq([1, 1, 1, 2, 3, 3]) // [2: 1, 3: 2, 1: 3]
freq([true, true, true, false, true]) // [false: 1, true: 4]
요소를 해시 가능하게 만들 수 없는 경우 튜플로 할 수 있습니다.
func freq<S: SequenceType where S.Generator.Element: Equatable>(seq: S) -> [(S.Generator.Element, Int)] {
let empty: [(S.Generator.Element, Int)] = []
return reduce(seq, empty) {
(var accu: [(S.Generator.Element,Int)], element) in
for (index, value) in enumerate(accu) {
if value.0 == element {
accu[index].1++
return accu
}
}
return accu + [(element, 1)]
}
}
freq(["a", "a", "a", "b", "b"]) // [("a", 3), ("b", 2)]
나는 내부 루프를 피하고 가능한 한 .map을 사용하는 것을 좋아합니다.따라서 문자열 배열이 있으면 다음을 수행하여 발생 횟수를 계산할 수 있습니다.
var occurances = ["tuples", "are", "awesome", "tuples", "are", "cool", "tuples", "tuples", "tuples", "shades"]
var dict:[String:Int] = [:]
occurances.map{
if let val: Int = dict[$0] {
dict[$0] = val+1
} else {
dict[$0] = 1
}
}
인쇄물
["tuples": 5, "awesome": 1, "are": 2, "cool": 1, "shades": 1]
스위프트 4
let array = ["FOO", "FOO", "BAR", "FOOBAR"]
// Merging keys with closure for conflicts
let mergedKeysAndValues = Dictionary(zip(array, repeatElement(1, count: array.count)), uniquingKeysWith: +)
// mergedKeysAndValues is ["FOO": 2, "BAR": 1, "FOOBAR": 1]
또 다른 방법은 필터 방법을 사용하는 것입니다.나는 가장 우아하다고 생각합니다.
var numberOfOccurenses = countedItems.filter(
{
if $0 == "FOO" || $0 == "BAR" || $0 == "FOOBAR" {
return true
}else{
return false
}
}).count
이 함수를 사용하여 배열에 있는 항목의 발생 횟수를 계산할 수 있습니다.
func checkItemCount(arr: [String]) {
var dict = [String: Any]()
for x in arr {
var count = 0
for y in arr {
if y == x {
count += 1
}
}
dict[x] = count
}
print(dict)
}
다음과 같이 구현할 수 있습니다.
let arr = ["FOO", "FOO", "BAR", "FOOBAR"]
checkItemCount(arr: arr)
public extension Sequence {
public func countBy<U : Hashable>(_ keyFunc: (Iterator.Element) -> U) -> [U: Int] {
var dict: [U: Int] = [:]
for el in self {
let key = keyFunc(el)
if dict[key] == nil {
dict[key] = 1
} else {
dict[key] = dict[key]! + 1
}
//if case nil = dict[key]?.append(el) { dict[key] = [el] }
}
return dict
}
let count = ["a","b","c","a"].countBy{ $0 }
// ["b": 1, "a": 2, "c": 1]
struct Objc {
var id: String = ""
}
let count = [Objc(id: "1"), Objc(id: "1"), Objc(id: "2"),Objc(id: "3")].countBy{ $0.id }
// ["2": 1, "1": 2, "3": 1]
extension Collection where Iterator.Element: Comparable & Hashable {
func occurrencesOfElements() -> [Element: Int] {
var counts: [Element: Int] = [:]
let sortedArr = self.sorted(by: { $0 > $1 })
let uniqueArr = Set(sortedArr)
if uniqueArr.count < sortedArr.count {
sortedArr.forEach {
counts[$0, default: 0] += 1
}
}
return counts
}
}
// Testing with...
[6, 7, 4, 5, 6, 0, 6].occurrencesOfElements()
// Expected result (see number 6 occurs three times) :
// [7: 1, 4: 1, 5: 1, 6: 3, 0: 1]
계수 정렬의 첫 번째 단계.
var inputList = [9,8,5,6,4,2,2,1,1]
var countList : [Int] = []
var max = inputList.maxElement()!
// Iniate an array with specific Size and with intial value.
// We made the Size to max+1 to integrate the Zero. We intiated the array with Zeros because it's Counting.
var countArray = [Int](count: Int(max + 1), repeatedValue: 0)
for num in inputList{
countArray[num] += 1
}
print(countArray)
두 가지 솔루션:
- 용사를 합니다.
forEach
모양의
let array = [10,20,10,40,10,20,30]
var processedElements = [Int]()
array.forEach({
let element = $0
// Check wether element is processed or not
guard processedElements.contains(element) == false else {
return
}
let elementCount = array.filter({ $0 == element}).count
print("Element: \(element): Count \(elementCount)")
// Add Elements to already Processed Elements
processedElements.append(element)
})
- 재귀 함수 사용
let array = [10,20,10,40,10,20,30]
self.printElementsCount(array: array)
func printElementsCount(array: [Int]) {
guard array.count > 0 else {
return
}
let firstElement = array[0]
let filteredArray = array.filter({ $0 != firstElement })
print("Element: \(firstElement): Count \(array.count - filteredArray.count )")
printElementsCount(array: filteredArray)
}
import Foundation
var myArray:[Int] = []
for _ in stride(from: 0, to: 10, by: 1) {
myArray.append(Int.random(in: 1..<6))
}
// Method 1:
var myUniqueElements = Set(myArray)
print("Array: \(myArray)")
print("Unique Elements: \(myUniqueElements)")
for uniqueElement in myUniqueElements {
var quantity = 0
for element in myArray {
if element == uniqueElement {
quantity += 1
}
}
print("Element: \(uniqueElement), Quantity: \(quantity)")
}
// Method 2:
var myDict:[Int:Int] = [:]
for element in myArray {
myDict[element] = (myDict[element] ?? 0) + 1
}
print(myArray)
for keyValue in myDict {
print("Element: \(keyValue.key), Quantity: \(keyValue.value)")
}
계산을 하는 구조는
struct OccureCounter<Item: Hashable> {
var dictionary = [Item: Int]()
mutating func countHere(_ c: [Item]) {
c.forEach { add(item: $0) }
printCounts()
}
mutating func add(item: Item) {
if let value = dictionary[item] {
dictionary[item] = value + 1
} else {
dictionary[item] = 1
}
}
func printCounts() {
print("::: START")
dictionary
.sorted { $0.value > $1.value }
.forEach { print("::: \($0.value) — \($0.key)") }
let all = dictionary.reduce(into: 0) { $0 += $1.value }
print("::: ALL: \(all)")
print("::: END")
}
}
사용.
struct OccureTest {
func test() {
let z: [Character] = ["a", "a", "b", "a", "b", "c", "d", "e", "f"]
var counter = OccureCounter<Character>()
counter.countHere(z)
}
}
인쇄:
::: START
::: 3 — a
::: 2 — b
::: 1 — c
::: 1 — f
::: 1 — e
::: 1 — d
::: ALL: 9
::: END
언급URL : https://stackoverflow.com/questions/30545518/how-to-count-occurrences-of-an-element-in-a-swift-array
'programing' 카테고리의 다른 글
노드 패키지(Grunt)가 설치되었지만 사용할 수 없음 (0) | 2023.08.05 |
---|---|
MariaDB - 사용자를 통해 로그인할 수 없음 - 암호 문자 인코딩 오류 (0) | 2023.08.05 |
페이스북에서 반환된 X-FB-DEBUG 헤더는 무엇입니까? (0) | 2023.08.05 |
오류: xxx 테이블에 대한 테이블스페이스가 있습니다.가져오기 전에 테이블스페이스를 삭제하십시오. (0) | 2023.08.05 |
선형 레이아웃에서 여백을 프로그래밍 방식으로 설정 (0) | 2023.08.05 |