How to Count Occurrences of an Element in a Swift Array

How to count occurrences of an element in a Swift array?

Swift 3 and Swift 2:

You can use a dictionary of type [String: Int] to build up counts for each of the items in your [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)")
}

output:

BAR occurs 1 time(s)
FOOBAR occurs 1 time(s)
FOO occurs 2 time(s)

Swift 4:

Swift 4 introduces (SE-0165) the ability to include a default value with a dictionary lookup, and the resulting value can be mutated with operations such as += and -=, so:

counts[item] = (counts[item] ?? 0) + 1

becomes:

counts[item, default: 0] += 1

That makes it easy to do the counting operation in one concise line using 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]"

Swift 4: reduce(into:_:)

Swift 4 introduces a new version of reduce that uses an inout variable to accumulate the results. Using that, the creation of the counts truly becomes a single line:

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]

Or using the default parameters:

let counts = arr.reduce(into: [:]) { $0[$1, default: 0] += 1 }

Finally you can make this an extension of Sequence so that it can be called on any Sequence containing Hashable items including Array, ArraySlice, String, and String.SubSequence:

extension Sequence where Element: Hashable {
var histogram: [Element: Int] {
return self.reduce(into: [:]) { counts, elem in counts[elem, default: 0] += 1 }
}
}

This idea was borrowed from this question although I changed it to a computed property. Thanks to @LeoDabus for the suggestion of extending Sequence instead of Array to pick up additional types.

Examples:

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]

how to count specific items in array in swift

A fast, compact and elegant way to do it is by using the reduce method:

let count = OSes.reduce(0) { $1 == "Android" ? $0 + 1 : $0 }

It's more compact than a for loop, and faster than a filter, because it doesn't generate a new array.

The reduce method takes an initial value, 0 in our case, and a closure, applied to each element of the array.

The closure takes 2 parameters:

  • the value at the previous iteration (or the initial value, 0 in our case)
  • the array element for the current iteration

The value returned by the closure is used as the first parameter in the next iteration, or as the return value of the reduce method when the last element has been processed

The closure simply checks if the current element is Android:

  • if not, it returns the aggregate value (the first parameter passed to the closure)
  • if yes, it returns that number plus one

How to count occurrences of an element in a Swift array of objects with different conditions

the answer was very simple it was in the extension of my class and by adding the Equatable,

extension notificationManager: Equatable {

static func ==(lhs: notificationManager, rhs: notificationManager) -> Bool {
return lhs.fromwho.username == rhs.fromwho.username && lhs.forwho.username == rhs.forwho.username && lhs.activity.objectId == rhs.activity.objectId
}}

and then i just add the count

     for item in orignalNotifs {
notificationManager.Notifcounts[item] = (notificationManager.Notifcounts[item] ?? 0) + 1
}

How to count occurrences of two elements in Swift?

How will could iterate over Sequence & get an occurrence of data.

var greetingArr = Array("Hello, playground")
var occurrences = Dictionary(greetingArr.map{($0, 1)}) { i, j in i + 1 }
//or Dictionary(greetingArr.map{($0, 1)}) { $0 + $1 }
//or Dictionary(greetingArr.map{($0, 1)}, uniquingKeysWith: +)

// occurrences ⬻ ["e": 1, "l": 3, "o": 2, "n": 1, "a": 1, ",": 1, "y": 1
// " ": 1, "d": 1, "H": 1, "u": 1, "p": 1, "r": 1, "g": 1]

In this case, an iterator is your entry Array & wants to find an occurrence of a particular combination of its two properties (important & urgent).
If those property is String type:

var dict = Dictionary(entry.map{($0.important + "-" + $0.urgent, 1)}) { $0 + $1 }

If there is a function that gives Int, From those two properties.

important,urgent ⤖ 3, important,none ⤖ 2, none,urgent ⤖ 0 & none,none ⤖ 4

then you can map entry.map{($0.intFromTwoProperties, 1)} instead of the previous mapping,

but that will give you an occurrence dictionary with that Int key.

How to count occurrences of an element in a Swift / array?

How about something like this?

//: Playground - noun: a place where people can play

import UIKit

let array = ["julien: Yes","elie: Yes", "Mark: No", "Jean: Yes"]
let results = array.map({ $0.lowercaseString.containsString("yes") })
let count = results.filter({ $0 == true }).count
count // 3

You can also make it a one liner:

let count = array.filter({ $0.lowercaseString.containsString("yes") }).count 

Note: I also added a check for case sensitivity just incase the data source was inconsistent

How to know how many time each element appears in an array?

I will solve this problem by creating hash table or dictionary with keys of type the same as array elements and integers as values. This structure will store values from array. Walking through array you can:

  1. Add element to dictionary is if it not already exists with value as "key" and 1 as "value".
  2. If element already exists - increment "value" by one of element "Key| == element.
    After walking whole array you will have dictionary with unique elements as dictionary keys and number of repetitions as values

Count occurrences of values in dictionaries in Swift

Here is a possible method of doing this, which should be slightly faster than excessive use of loops.

Method:

  1. Split each review into its individual words.
  2. Create a dictionary with the key being the review word and the value being the frequency.
  3. Loop through every topic, then loop through every keyword in that topic.
  4. If the keyword is in reviewsDict, get the number of occurrences and add it on to count's occurrences.
  5. Return dictionary result containing topics and their frequencies.

Solution:

func countOccurance(topics: [String: [String]], reviews: [String]) -> [String : Int] {
var reviewsDict: [String: Int] = [:]
for review in reviews {
let reviewWords = review.components(separatedBy: CharacterSet.letters.inverted)

for word in reviewWords {
guard !word.isEmpty else { continue }
reviewsDict[word.lowercased(), default: 0] += 1
}
}

var count: [String: Int] = [:]
for (topic, topicKeywords) in topics {
for topicKeyword in topicKeywords {
guard let occurrences = reviewsDict[topicKeyword] else { continue }
count[topic, default: 0] += occurrences
}
}

return count
}

Result:

0 : (key: "price", value: 2)
1 : (key: "business", value: 1)

Swift: number of occurrences of element in Array as a percentage?

Maybe something like this?

var filteredArray = [1,2,4,5,2,1,2,1,5,5]

var counts:[Int: Double] = [:]

for item in filteredArray {
counts[item] = (counts[item] ?? 0) + (1.0/Double(filteredArray.count))
}

print(counts)

// Output:
// [5: 0.30000000000000004, 2: 0.30000000000000004, 4: 0.10000000000000001, 1: 0.30000000000000004]

Filter array with most occurrences of element in swift

You can group the items into a dictionary and compare the number of items in each group

let mostFrequent = Dictionary(grouping: array1, by: {$0})
.max(by: {$0.value.count < $1.value.count})?.value ?? []

The issue with the above is that if there are two or more values with the same count only one will be selected.

The below solution handles when there are multiple max counts, I couldn't write it as a single line expression though

let dictionary = Dictionary(grouping: array1, by: {$0})
let max = dictionary.max(by: {$0.value.count < $1.value.count})?.value.count ?? 0
let mostFrequent = dictionary.filter { $0.value.count == max }.values


Related Topics



Leave a reply



Submit