create dictionary from objects and keys arrays in swift 2 - ios

I have Keys array and Objects array and I want to create a dictionary that each key at index Y in keys array refers to the object at the same index Y in objects array i.e. I want to make code like this but in Swift 2:
NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithObjects:ObjectsArray forKeys:KeysArray];

let keys = [1,2,3,4]
let values = [10, 20, 30, 40]
assert(keys.count == values.count)
var dict:[Int:Int] = [:]
keys.enumerate().forEach { (i) -> () in
dict[i.element] = values[i.index]
}
print(dict) // [2: 20, 3: 30, 1: 10, 4: 40]
or more functional and generic approach
func foo<T:Hashable,U>(keys: Array<T>, values: Array<U>)->[T:U]? {
guard keys.count == values.count else { return nil }
var dict:[T:U] = [:]
keys.enumerate().forEach { (i) -> () in
dict[i.element] = values[i.index]
}
return dict
}
let d = foo(["a","b"],values:[1,2]) // ["b": 2, "a": 1]
let dn = foo(["a","b"],values:[1,2,3]) // nil

This is a generic solution
func dictionaryFromKeys<K : Hashable, V>(keys:[K], andValues values:[V]) -> Dictionary<K, V>
{
assert((keys.count == values.count), "number of elements odd")
var result = Dictionary<K, V>()
for i in 0..<keys.count {
result[keys[i]] = values[i]
}
return result
}
let keys = ["alpha", "beta", "gamma", "delta"]
let values = [1, 2, 3, 4]
let dict = dictionaryFromKeys(keys, andValues:values)
print(dict)

Try this:
let dict = NSDictionary(objects: <Object_Array>, forKeys: <Key_Array>)
//Example
let dict = NSDictionary(objects: ["one","two"], forKeys: ["1","2"])

let keyArray = [1,2,3,4]
let objectArray = [10, 20, 30, 40]
let dictionary = NSMutableDictionary(objects: objectArray, forKeys: keyArray)
print(dictionary)
Output:-
{
4 = 40;
3 = 30;
1 = 10;
2 = 20;
}

Related

Map value in particular key in array of dictionary

Map value the particular key wherever presents in array of dictionary and replace it in same array.
We need to update pan_card key 0 to 1, in occurence of array of dictionary.
let keyToUpdate = "pan_card"
var arrayOfDictionary = [[String:Any]]()
var firstDict = [String:Any]()
firstDict["passport"] = 0
firstDict["ration_card"] = 0
firstDict["pan_card"] = 0
var arrayDict = [String : Any]()
arrayDict["currentObject"] = firstDict
arrayDict["title"] = "Documents list"
var secondDict = [String:Any]()
secondDict["dl"] = 0
secondDict["voter"] = 0
secondDict["pan_card"] = 0
//let dic = secondDict.filter({ $0.value as! NSNumber != 0})
//secondDict = dic
//print(secondDict)
//let dictionary = ["foo": 1, "bar": 2, "baz": 5]
//
//let newDictionary = dictionary.mapValues { value in
// return value - value
//}
//print(dictionary)
//print(newDictionary)
var arrayDict2 = [String : Any]()
arrayDict2["currentObject"] = secondDict
arrayDict2["title"] = "Second Documents list"
arrayOfDictionary.append(arrayDict)
arrayOfDictionary.append(arrayDict2)
//print(arrayOfDictionary)
for (index, dictionary) in arrayOfDictionary.enumerated() {
let dict = dictionary
let newDictionary = (dict["currentObject"] as![String:Any]).mapValues { value in
return 1
}
arrayOfDictionary[index] = newDictionary
}
print(arrayOfDictionary)
This code updating every key in currentObject
and tried this as well, but it adding new key
for (index, dictionary) in arrayOfDictionary.enumerated() {
var dict = dictionary
// let newDictionary = (dict["currentObject"] as![String:Any]).mapValues { value in
// return 1
// }
var newDictionary = [String: Any]()
for (key, value) in dict["currentObject"] as![String:Any] {
dict[keyToUpdate, default: value] = 1
}
arrayOfDictionary[index] = dict
}
print(arrayOfDictionary)
I need output like below
Original value
[["currentObject": ["passport": 0, "pan_card": 0, "ration_card": 0], "title": "Documents list"], ["currentObject": ["pan_card": 0, "dl": 0, "voter": 0], "title": "Second Documents list"]]
after update
[["currentObject": ["passport": 0, "pan_card": 1, "ration_card": 0], "title": "Documents list"], ["currentObject": ["pan_card": 1, "dl": 0, "voter": 0], "title": "Second Documents list"]]
Referred Document Link
We knows manually iterating and updating values, we wanted to done with higher order function.
Using a recursive method that performs the update
func update(key:String, in dict: [String:Any], with value: Any) -> [String:Any] {
var out = [String:Any]()
if let _ = dict[key] {
out = dict
out[key] = value
} else {
dict.forEach {
if let innerDict = $0.value as? [String:Any] {
out[$0.key] = update(key: key, in: innerDict, with: value)
} else {
out[$0.key] = $0.value
}
}
}
return out
}
we can use a simple map call
var original = [["currentObject": ["passport": 0, "pan_card": 0, "ration_card": 0], "title": "Documents list"], ["currentObject": ["pan_card": 0, "dl": 0, "voter": 0], "title": "Second Documents list"]]
let result = original.map{ update(key: "pan_card", in: $0, with: 1)}
The update function was based on this answer

Array of Integers to Arrays of Ranges

My Task:
I need to divide the Array into several Arrays of Arrays with the following properties:
every subarray is a range of continuous integer. As example [1,2,3,4,5] will be [[1,5]].
When there are no contiguous integer create a new subarray. As example [1,2,4,5] will be [[1,2], [4,5]]
Example:
If I have this Array of Integers - [0, 1, 5, 6, 3, 7]
Expected Result - [[0, 1], [3], [5, 7]]
I already tried this:
let array: [Int] = [0, 1, 3, 4, 5, 6, 7]
var group: [[Int]] = []
var temp: [Int] = [Int]()
for (index, element) in array.enumerated() {
if index + 1 < array.count {
let nextElement = array[index + 1]
let step = nextElement - element
// temp.append(element)
if(step) == 1 { // Until it's in range
temp.append(element)
} else { // One-by-one
temp.append(element)
group.append(temp)
temp = [Int]()
group.append([nextElement])
}
} else {
print(index)
}
}
print(group)
From my code, I get this result - [[0, 1], [3]]
There is an API, IndexSet:
It's not clear what you want, your examples are ambiguous.
If you want an array of ranges
let indexSet = IndexSet(array)
let rangeView = indexSet.rangeView
let group = rangeView.map { $0.indices.startIndex..<$0.indices.endIndex }
If you want a grouped array by ranges
let indexSet = IndexSet(array)
let rangeView = indexSet.rangeView
let group = rangeView.map { Array($0.indices) }
This is the best approach I found:
let array: [Int] = [0, 1, 5, 6, 3, 7].sorted();
var group: [[Int]] = []
var temp: [Int] = [Int]()
var lastElement: Int = -1;
for (index, element) in array.enumerated() {
if lastElement == -1 {
temp.append(element);
}
else {
if element - lastElement == 1 {
temp.append(element);
}
else {
group.append(temp);
temp = [Int]();
temp.append(element);
}
}
lastElement = element;
}
if temp.count > 0 {
group.append(temp);
}
print(group)
Here is my solution. Rather than manually managing indexes, I use two iterators. One which advances along denoting the "start" of runs, and one which races ahead to find the "ends" of runs.
I've gentrified my code to work over any Sequence (not just Array), and any Strideable type (any type that defines distance(to:), not necessarily just Int).
extension Sequence where Element: Strideable {
func splitConsequtiveRuns() -> [[Element]] {
var runs = [[Element]]()
var runStartIterator = self.makeIterator()
while let startElement = runStartIterator.next() {
var runEndIterator = runStartIterator
var prevElement = startElement
var run = [startElement]
while let nextElement = runEndIterator.next(),
prevElement.distance(to: nextElement) == 1 {
_ = runStartIterator.next() // advance the "start" iterator, to keep pace
prevElement = nextElement // update this, for use in then next loop's comparison
run.append(nextElement)
}
runs.append(run)
}
return runs
}
}
let array: [Int] = [0...3, 8...8, 10...15].flatMap { $0 }
print(array.splitConsequtiveRuns()) // => [[0, 1, 2, 3], [8], [10, 11, 12, 13, 14, 15]]

sort array of anyobject Swift 3

I am trying to sort an array of anyobject, but not able to do it.I get some data from Parse database in AnyObject format. As per below data, I want to sort this AnyObject array by "NAME". Below is my code -
let sortedArray = (myArray as! [AnyObject]).sorted(by: { (dictOne, dictTwo) -> Bool in
let d1 = dictOne["NAME"]! as AnyObject; // this line gives error "Ambiguous use of subscript"
let d2 = dictTwo["NAME"]! as AnyObject; // this line gives error "Ambiguous use of subscript"
return d1 < d2
})
myArray looks like this -
{
LINK = "www.xxx.com";
MENU = Role;
"MENU_ID" = 1;
NAME = "A Name";
SUBMENU = "XXX";
"Training_ID" = 2;
},
{
LINK = "www.xyz.com";
MENU = Role;
"MENU_ID" = 2;
NAME = "B name";
SUBMENU = "jhjh";
"Training_ID" = 6;
},
{
LINK = "www.hhh.com";
MENU = Role;
"MENU_ID" = 3;
NAME = "T name";
SUBMENU = "kasha";
"Training_ID" = 7;
},
{
LINK = "www.kadjk.com";
MENU = Role;
"MENU_ID" = 5;
NAME = "V name";
SUBMENU = "ksdj";
"Training_ID" = 1;
},
{
LINK = "www.ggg.com";
MENU = Role;
"MENU_ID" = 4;
NAME = "K name";
SUBMENU = "idiot";
"Training_ID" = 8;
},
{
LINK = "www.kkk.com";
MENU = Role;
"MENU_ID" = 6;
NAME = "s name";
SUBMENU = "BOM/ABOM/BSM";
"Training_ID" = 12;
}
Any help would be much appreciated. Thanks!
It's not [AnyObject] (array of I-have-no-idea), it's array of dictionaries [[String:Any]]. Be more specific, this resolves the error.
In Swift 3 the compiler must know the specific type of all subscripted objects.
let sortedArray = (myArray as! [[String:Any]]).sorted(by: { (dictOne, dictTwo) -> Bool in
let d1 = dictOne["NAME"]! as String
let d2 = dictTwo["NAME"]! as String
return d1 < d2
})
Why are converting array to [AnyObject] instead of that convert the array to the [[String:Any]] means Array of Dictionary and tell the compiler that array contains Dictionary as objects.
if let array = myArray as? [[String:Any]] {
let sortedArray = array.sorted(by: { $0["NAME"] as! String < $1["NAME"] as! String })
}
Note: As of you are having NAME key with String value in your each dictionaries of array I have force wrapped it with the subscript.
You can use below function if you want
//function to sort requests
func sortRequests(dataToSort: [[String:Any]]) -> [[String:Any]] {
print("i am sorting the requests...")
var returnData = [[String:Any]]()
returnData = dataToSort
returnData.sort{
let created_date0 = $0["date"] as? Double ?? 0.0
let created_date1 = $1["date"] as? Double ?? 0.0
return created_date0 > created_date1
}
return returnData
}

Swift 3: Accessing nested dictionary from returns nil?

I'm having a problem trying to access a nested Dictionary, which seems to return nil.
Here's the output my info of type Dictionary<String, Any>:
info = ["list_order": 1, "name": Some Text, "id": 1, "menu_items": {
1 = {
"food_name" = "String";
"food_picture" = "link";
"food_price" = "2.00";
};
2 = {
"food_name" = "String";
"food_picture" = "link";
"food_price" = "5.00";
id = 2;
};
}]
The output of info["menu_items"]:
info["menu_items"] = {
1 = {
"food_name" = "String";
"food_picture" = "link";
"food_price" = "2.00";
id = 1;
};
2 = {
"food_name" = "String";
"food_picture" = "link";
"food_price" = "5.00";
id = 2;
};
}
However, the following assigning produces a nil in test:
let test = info["menu_items"] as? Dictionary<Int, Any>
Is there something not obvious or am I not understanding basic fundamentals?
If your key is not Int type then most probably it is of String type, try once using [String: Any].
if let menuItems = info["menu_items"] as? [String: Any] {
print(menuItems)
}

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

I've seen a few examples of this but all of those seem to rely on knowing which element you want to count the occurrences of. My array is generated dynamically so I have no way of knowing which element I want to count the occurrences of (I want to count the occurrences of all of them). Can anyone advise?
EDIT:
Perhaps I should have been clearer, the array will contain multiple different strings (e.g.
["FOO", "FOO", "BAR", "FOOBAR"]
How can I count the occurrences of foo, bar and foobar without knowing what they are in advance?
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]
array.filter{$0 == element}.count
With Swift 5, according to your needs, you may choose one of the 7 following Playground sample codes to count the occurrences of hashable items in an array.
#1. Using Array's reduce(into:_:) and Dictionary's subscript(_:default:) subscript
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. Using repeatElement(_:count:) function, zip(_:_:) function and Dictionary's init(_:uniquingKeysWith:)initializer
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. Using a Dictionary's init(grouping:by:) initializer and mapValues(_:) method
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. Using a Dictionary's init(grouping:by:) initializer and map(_:) method
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. Using a for loop and Dictionary's subscript(_:) 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. Using NSCountedSet and NSEnumerator's map(_:) method (requires Foundation)
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. Using NSCountedSet and AnyIterator (requires Foundation)
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)]
Credits:
Swift Idioms
generic on Collection, using Dictionary
I updated oisdk's answer to Swift2.
16/04/14 I updated this code to Swift2.2
16/10/11 updated to Swift3
Hashable:
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
}
}
}
Equatable:
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)]
}
}
}
Usage
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)
Use an NSCountedSet. In Objective-C:
NSCountedSet* countedSet = [[NSCountedSet alloc] initWithArray:array];
for (NSString* string in countedSet)
NSLog (#"String %# occurs %zd times", string, [countedSet countForObject:string]);
I assume that you can translate this into Swift yourself.
How about:
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]
It's generic, so it'll work with whatever your element is, as long as it's hashable:
freq([1, 1, 1, 2, 3, 3]) // [2: 1, 3: 2, 1: 3]
freq([true, true, true, false, true]) // [false: 1, true: 4]
And, if you can't make your elements hashable, you could do it with tuples:
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)]
I like to avoid inner loops and use .map as much as possible.
So if we have an array of string, we can do the following to count the occurrences
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
}
}
prints
["tuples": 5, "awesome": 1, "are": 2, "cool": 1, "shades": 1]
Swift 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]
An other approach would be to use the filter method. I find that the most elegant
var numberOfOccurenses = countedItems.filter(
{
if $0 == "FOO" || $0 == "BAR" || $0 == "FOOBAR" {
return true
}else{
return false
}
}).count
You can use this function to count the occurence of the items in array
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)
}
You can implement it like this -
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]
First Step in Counting Sort.
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)
Two Solutions:
Using forEach loop
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)
})
Using Recursive Function
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)")
}
The structure which do the count
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")
}
}
Usage
struct OccureTest {
func test() {
let z: [Character] = ["a", "a", "b", "a", "b", "c", "d", "e", "f"]
var counter = OccureCounter<Character>()
counter.countHere(z)
}
}
It prints:
::: START
::: 3 — a
::: 2 — b
::: 1 — c
::: 1 — f
::: 1 — e
::: 1 — d
::: ALL: 9
::: END

Resources