Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Most common array elements

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.

like image 359
TimWhiting Avatar asked Dec 22 '14 23:12

TimWhiting


People also ask

What are elements 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.

What is the most common in a list of numbers?

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.


2 Answers

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 }
    }
}
like image 56
Airspeed Velocity Avatar answered Oct 18 '22 05:10

Airspeed Velocity


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)
like image 3
Cody Weaver Avatar answered Oct 18 '22 05:10

Cody Weaver