Преобразовать NSArray в массив уникальных значений, отсортированных по частоте в Objective- C или Swift - PullRequest
1 голос
/ 01 апреля 2020

У меня есть массив значений, в котором я хотел бы подсчитать частоту каждого уникального значения, а затем создать новый массив уникальных значений, отсортированных по частоте.

Например, для массива следующим образом:

 vals = {0,0,0,2,0,1,2}

Я бы хотел получить массив {0,2,1}, поскольку 0 является наиболее распространенным значением, 2 является вторым наиболее распространенным, а 1 - наименее распространенным. Обратите внимание, тот факт, что это числа, не имеет значения. Они так же легко могут быть строками.

Я подумал, что смогу использовать nssortdescriptor, как в:

NSSortDescriptor *sorter = [NSSortDescriptor sortDescriptorWithKey:@"wordCount" ascending:NO];
NSArray *sortedcats = [vals sortedArrayUsingDescriptors:@[sorter]];

Однако это не сортирует их по уровню и не дает отфильтровывать дубликаты.

Спасибо за любые предложения.

1 Ответ

1 голос
/ 01 апреля 2020

Есть пара подходов

Конвертировать в Set/NSSet и затем отсортировать.

Swift

let vals = [0,0,0,2,0,1,2]
let uniqued = Set(vals).sorted()

Этот же метод будет также работать с NSSet + NSSortDescriptor в Objective C, но, очевидно, более длинной строкой для записи.

или более классический c базовый подход

let nsvals: NSArray = [3,0,0,2,0,1,2]
let nsuniquedAndSorted = nsvals.value(forKeyPath: "@distinctUnionOfObjects.self")

Что круто, поскольку @distinctUnionOfObjects также сортирует бесплатно. Есть много хитрых трюков с ключом-значением в том же духе здесь .

РЕДАКТИРОВАТЬ

Для сортировки по частоте можно использовать метод подсчета Затем юниксы прибегают к этому.

let sortedByIncidence = uniqued
    .map { outer in return (outer, vals.filter({$0 == outer}).count) }
    .sorted { $0.1 > $1.1 }
    .map { $0.0 } 
...