Count Elements of Array Matching Condition in Swift

Count elements of array matching condition in Swift

Like this:

 let a: [Int] = ...
let count = a.filter({ $0 % 2 == 0 }).count

Count number of items in an array with a specific property value

Use filter method:

let managersCount = peopleArray.filter { (person : Person) -> Bool in
return person.isManager!
}.count

or even simpler:

let moreCount = peopleArray.filter{ $0.isManager! }.count

Count string elements in an array in a multidimensional array

If you want to use filter, something like this should work with your struct:

var laptopTotal = playerStock.filter { $0.productName == "laptop" }.count

Swift count each array based on conditional date range

OK, my friend. I threw together something you can dump in a playground. There's a lot of minor issues going on with your code, so I cleaned it up a little. First thing's first.

  1. You don't need to put an initializer on a struct. You get it "for free", so your declaration will look like so:
// CapitalizedCamelCase for classes, structs, enums & typedefs
struct Jogs {
// You get an initializer for "free" with a struct
var jogTitle: String
var jogDate: Date
}

Then, once you declare all your structs and dump them in an array, you'll want to use filter. It'll look something like this:

let filteredJogs = jogs.filter { $0.jogDate >= Date() }
let filteredJogCount = filteredJogs.count

So anyway, here's some code you can dump in a playground and play around with:

// CapitalizedCamelCase for classes, structs, enums & typedefs
struct Jogs {
// You get an initializer for "free" with a struct
var jogTitle: String
var jogDate: Date
}

// I'm doing this b/c I'm lazy and don't wanna create the dates "by hand"
func randomDateGenerator() -> [Date] {
var arrayOfDates: [Date] = []
let days = Array(1...30)
days.forEach { day in
var components = DateComponents()
components.month = 4
components.day = day
components.year = 2020

let newDate = Calendar.current.date(from: components)! // Don't force unwrap (!) in production code
arrayOfDates.append(newDate)
}

return arrayOfDates
}

let today: Date = {
var components = DateComponents()
components.month = 4
components.day = 30
components.year = 2020

return Calendar.current.date(from: components)!
}()

enum TimeSpan {
case lastWeek
case lastTwoWeeks
case lastMonth
}

var jogNames = ["a", "b", "c", "d", "e", "f", "g", "h", "i", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z", "A", "B", "C", "D"]
let jogDates = randomDateGenerator()

var arrayOfJogs: [Jogs] = []

zip(jogNames, jogDates).forEach { title, date in
let structToAdd = Jogs(jogTitle: title,
jogDate: date)
arrayOfJogs.append(structToAdd)
}

func getJogs(for timeSpan: TimeSpan, jogs: [Jogs], today: Date) -> [Jogs] {
var referenceDate: Date

switch timeSpan {
case .lastWeek:
referenceDate = Calendar.current.date(byAdding: .day, value: -7, to: today)!
case .lastTwoWeeks:
referenceDate = Calendar.current.date(byAdding: .day, value: -14, to: today)!
case .lastMonth:
referenceDate = Calendar.current.date(byAdding: .day, value: -30, to: today)!
}

return jogs.filter { $0.jogDate >= referenceDate }
}

let lastSevenDays = getJogs(for: .lastWeek, jogs: arrayOfJogs, today: today)

lastSevenDays.forEach { filteredJog in
print(filteredJog.jogDate)
}

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]

Find the pair in array with condition

Try with this:

func findPair(list: [Int], _ sum: Int) -> (Int, Int)? {
//save list of value of sum - item.
var hash = Set<Int>()
var dictCount = [Int: Int]()
for item in list {

//keep track of count of each element to avoid problem: [2, 3, 5], 10 -> result = (5,5)
if (!dictCount.keys.contains(item)) {
dictCount[item] = 1
} else {
dictCount[item] = dictCount[item]! + 1
}
//if my hash does not contain the (sum - item) value -> insert to hash.
if !hash.contains(sum-item) {
hash.insert(sum-item)
}

//check if current item is the same as another hash value or not, if yes, return the tuple.
if hash.contains(item) &&
(dictCount[item] > 1 || sum != item*2) // check if we have 5+5 = 10 or not.
{
return (item, sum-item)
}
}
return nil
}

How to check if an element is in an array

Swift 2, 3, 4, 5:

let elements = [1, 2, 3, 4, 5]
if elements.contains(5) {
print("yes")
}

contains() is a protocol extension method of SequenceType (for sequences of Equatable elements) and not a global method as in
earlier releases.

Remarks:

  • This contains() method requires that the sequence elements
    adopt the Equatable protocol, compare e.g. Andrews's answer.
  • If the sequence elements are instances of a NSObject subclass
    then you have to override isEqual:, see NSObject subclass in Swift: hash vs hashValue, isEqual vs ==.
  • There is another – more general – contains() method which does not require the elements to be equatable and takes a predicate as an
    argument, see e.g. Shorthand to test if an object exists in an array for Swift?.

Swift older versions:

let elements = [1,2,3,4,5]
if contains(elements, 5) {
println("yes")
}

Counting number of elements in an array of array of struct in Swift 5

Use the rawValue of the attributes and a default total of 0 on dictionary lookup to total the values:

func createIconCount(playerHand: [Card] ) -> [String : Int] {

var counts: [String: Int] = [:]

for card in playerHand {
counts[card.dateGroup.rawValue, default: 0] += 1
counts[card.countryGroup.rawValue, default: 0] += 1
counts[card.icon1.rawValue, default: 0] += 1
// Don't count icon2 if it is the same as icon1
if card.icon2 != card.icon1 {
counts[card.icon2.rawValue, default: 0] += 1
}
}

return counts
}

Creating an array of indices of cards with icon:

Instead of creating a count of the cards with a matching icon, you can create an array of the indices of the cards in the player's hand. Start by adding .enumerated to playerHand to get the indices, and then append the idx to the array. Here we use [] as the default dictionary lookup value creating an empty array if one doesn't already exist.

func createIconCount(playerHand: [Card] ) -> [String : [Int]] {

var counts: [String: [Int]] = [:]

for (idx, card) in playerHand.enumerated() {
counts[card.dateGroup.rawValue, default: []].append(idx)
counts[card.countryGroup.rawValue, default: []].append(idx)
counts[card.icon1.rawValue, default: []].append(idx)
// Don't count icon2 if it is the same as icon1
if card.icon2 != card.icon1 {
counts[card.icon2.rawValue, default: []].append(idx)
}
}

return counts
}

How to find all indices of the matching array elements in Swift

You can use enumerated and compactMap in combination to achieve this:

let indices = a.enumerated().compactMap { $1 > 4 ? $0 : nil }


Related Topics



Leave a reply



Submit