I need to find the most common (modal) elements in an array.
The simplest way I could think of was to set variables for each unique element, and assign a count variable for each one, which increases every time it is recorded in a for loop which runs through the array.
Unfortunately the size of the array is unknown and will be very large, so this method is useless.
I have come across a similar question in Objective-C that uses an NSCountedSet method to rank the array elements. Unfortunately I am very new to programming, and could only translate the first line into Swift.
The suggested method is as follows:
var yourArray: NSArray! // My swift translation
NSCountedSet *set = [[NSCountedSet alloc] initWithArray:yourArray];
NSMutableDictionary *dict=[NSMutableDictionary new];
for (id obj in set) {
[dict setObject:[NSNumber numberWithInteger:[set countForObject:obj]]
forKey:obj]; //key is date
}
NSLog(@"Dict : %@", dict);
NSMutableArray *top3=[[NSMutableArray alloc]initWithCapacity:3];
//which dict obj is = max
if (dict.count>=3) {
while (top3.count<3) {
NSInteger max = [[[dict allValues] valueForKeyPath:@"@max.intValue"] intValue];
for (id obj in set) {
if (max == [dict[obj] integerValue]) {
NSLog(@"--> %@",obj);
[top3 addObject:obj];
[dict removeObjectForKey:obj];
}
}
}
}
NSLog(@"top 3 = %@", top3);
In my program I will need to find the top five place names in an array.
Each item in an array is called an element, and each element is accessed by its numerical index. As shown in the preceding illustration, numbering begins with 0. The 9th element, for example, would therefore be accessed at index 8.
Show mode Note: The most common value is called the mode. The number that occurs most often in a data set is called the mode. Example: Find the mode of the numbers 2, 7, 13, 2 and 5.
edit: now with Swift 2.0 below
Not the most efficient of solutions but a simple one:
let a = [1,1,2,3,1,7,4,6,7,2]
var frequency: [Int:Int] = [:]
for x in a {
// set frequency to the current count of this element + 1
frequency[x] = (frequency[x] ?? 0) + 1
}
let descending = sorted(frequency) { $0.1 > $1.1 }
descending
now consists of an array of pairs: the value and the frequency,
sorted most frequent first. So the “top 5” would be the first 5 entries
(assuming there were 5 or more distinct values). It shouldn't matter how big the source array is.
Here's a generic function version that would work on any sequence:
func frequencies
<S: SequenceType where S.Generator.Element: Hashable>
(source: S) -> [(S.Generator.Element,Int)] {
var frequency: [S.Generator.Element:Int] = [:]
for x in source {
frequency[x] = (frequency[x] ?? 0) + 1
}
return sorted(frequency) { $0.1 > $1.1 }
}
frequencies(a)
For Swift 2.0, you can adapt the function to be a protocol extension:
extension SequenceType where Generator.Element: Hashable {
func frequencies() -> [(Generator.Element,Int)] {
var frequency: [Generator.Element:Int] = [:]
for x in self {
frequency[x] = (frequency[x] ?? 0) + 1
}
return frequency.sort { $0.1 > $1.1 }
}
}
a.frequencies()
For Swift 3.0:
extension Sequence where Self.Iterator.Element: Hashable {
func frequencies() -> [(Self.Iterator.Element,Int)] {
var frequency: [Self.Iterator.Element:Int] = [:]
for x in self {
frequency[x] = (frequency[x] ?? 0) + 1
}
return frequency.sorted { $0.1 > $1.1 }
}
}
For XCode 7.1 the solution is.
// Array of elements
let a = [7,3,2,1,4,6,8,9,5,3,0,7,2,7]
// Create a key for elements and their frequency
var times: [Int: Int] = [:]
// Iterate over the dictionary
for b in a {
// Every time there is a repeat value add one to that key
times[b] = (times[b] ?? 0) + 1
}
// This is for sorting the values
let descending = times.sort({$0.1 > $1.1})
// For sorting the keys the code would be
// let descending = times.sort({$0.0 > $1.0})
// Do whatever you want with sorted array
print(descending)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With