Сгруппировать список по частоте


26

Имея список целых чисел, сначала сгруппируйте элементы, которые встречаются чаще всего, затем сгруппируйте больше всего и т. Д., Пока каждый уникальный элемент в списке не будет сгруппирован один раз.


Примеры:

Входные данные: [1,2,3]

Выход: [[1,2,3]]


Входные данные: [1,1,1,2,2,3,3,4,5,6]

Выход: [[1],[2,3],[4,5,6]]


Входные данные: [1,1,1,4,5,6,6,6,7,7,8,8,8,8,8,8,8,9,5,6,5,6,5,6,5,6,-56]

Выход: [[6, 8],[5],[1],[7],[9,4,-56]]


Входные данные: []

Выход: []


Входные данные: (empty input)

Выход: ERROR/Undefined/Doesn't matter


правила

  • Группировки должны идти от максимальной частоты до минимальной частоты.
  • Внутренний порядок группировок произвольный (например, пример 3 может иметь [8,6]).
  • Это , выигрывает наименьшее количество байт.

Связанный


1
Может ли вывод быть в строковом формате? То есть. Список списков, но каждое число представлено символом вместо целого числа.
mb7744

Ответы:


6

Pyth , 8 7 байтов

_{M.g/Q

Попробуйте онлайн!

1 байт благодаря FryAmTheEggman.


@DigitalTrauma вы не можете; это в лямбде; есть неявная переменная k, которую я уже пропустил.
Утренняя монахиня

получил - спасибо за объяснение!
Цифровая травма


@MagicOctopusUrn спасибо.
Утренняя монахиня

7

Mathematica, 43 байта

Union/@SortBy[l=#,f=-l~Count~#&]~SplitBy~f&

Попробуйте онлайн! (Используя математику.)

В качестве альтернативы:

SortBy[Union[l=#],f=-l~Count~#&]~SplitBy~f&

5
Там нет встроенного?
Волшебная Урна Осьминога

Это GatherByвариант, не уверен, потому что я не знаю языка.
Волшебная Урна Осьминога

1
@carusocomputing Сортирует группы по первому появлению элементов в исходном списке, поэтому мне все равно придется сортировать группы впоследствии. Сортировав список в первую очередь, я могу сохранить байт с помощью SplitBy(а на SortByсамом деле это было бы более сложно, если бы я это сделал GatherByпервым).
Мартин Эндер

Интересно, что «должно быть в порядке от максимального до минимального» портит это?
Волшебная Урна Осьминога

@carusocomputing Точно.
Мартин Эндер

5

Python 2 , 145 141 байт

import collections as c,itertools as i;o=lambda n:lambda l:l[n]
print[map(o(0),g)for _,g in i.groupby(c.Counter(input()).most_common(),o(1))]

Попробуйте онлайн!

Это мое первое представление после нескольких лет чтения.

В основном он помещает все элементы в Counter (словарь количества каждого элемента в списке), а .most_common () размещает элементы в порядке убывания частоты. После этого нужно просто отформатировать элементы в правильный список.

Сохранено 4 байта благодаря ovs .


4
Добро пожаловать в PPCG :). Не становись таким зависимым, как я.
Волшебная Урна Осьминога

Создание собственной функции itemgetter 4 байта короче , чем импортировать его:o=lambda n:lambda l:l[n]
овс

5

JavaScript (ES6), 95 101 байт

a=>a.map(x=>(o[a.map(y=>n+=x!=y,n=0)|n]=o[n]||[])[x*x+(x>0)]=x,o=[])&&(F=o=>o.filter(a=>a))(o).map(F)

Как?

Для каждого элемента x входного массива a мы вычисляем число n элементов a , которые отличаются от x :

a.map(y => n += x != y, n = 0) | n

Мы используем индексы n и x, чтобы заполнить массив o :

(o[n] = o[n] || [])[x * x + (x > 0)] = x

Изменить : Поскольку JS не поддерживает отрицательные индексы массива, нам нужна формула x * x + (x > 0)для принудительного положительных индексов.

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

Тем не менее, и внешний массив, и внутренние массивы потенциально имеют много пустых слотов, которые мы хотим отфильтровать. Мы делаем это с помощью функции F , примененной к o и каждому из ее элементов:

F = o => o.filter(a => a)

Контрольные примеры


Я думаю, что Setэкономит вам байт a=>a.map(e=>(r[n=0,a.map(f=>n+=e!=f),n]||(r[n]=new Set)).add(e),r=[])&&r.filter(s=>s).map(s=>[...s]).
Нил

@Neil Это сильно отличается от моего нынешнего подхода. Может быть, вы должны опубликовать его как новый ответ?
Arnauld

Я не думал, что переход o[n]от массива к набору - это что-то иное, но я все равно уже отыграл ответ @ RickHitchcock, так что особого смысла нет.
Нил



2

Clojure, 74 байта

#(for[[_ g](sort-by(comp - key)(group-by val(frequencies %)))](map key g))

Выглядит довольно многословно: /


Ударь меня к нему (и побей меня несколькими байтами, умное использование, comp -чтобы полностью изменить!). Не так коротко, как другие языки, но я подумал, что это было забавно, поскольку в Clojure встроены «сгруппированные» и «частоты».
MattPutnam

Когда я читал описание задачи, я надеялся на 50 или 60 байтов, но фактическая реализация оказалась немного хитрее.
NikoNyrh

2

Perl 6 , 43 байта

*.Bag.classify(-*.value).sort».value».key

Попробуй это

Expanded:

*                   # WhateverCode lambda (this is the input)
                    # [1,1,1,2,2,3,3,4,5,6]

.Bag                # turn into a Bag
                    # (1=>3,5=>1,4=>1,3=>2,6=>1,2=>2).Bag

.classify(-*.value) # classify by how many times each was seen
                    # {-2=>[3=>2,2=>2],-3=>[1=>3],-1=>[5=>1,4=>1,6=>1]}

.sort\              # sort (this is why the above is negative)
                    # {-3=>[1=>3],-2=>[3=>2,2=>2],-1=>[5=>1,4=>1,6=>1]}

».value\            # throw out the classification
                    # ([1=>3],[3=>2,2=>2],[5=>1,4=>1,6=>1])

».key               # throw out the counts
                    # ([1],[3,2],[5,4,6])

Ух ты, я всегда забываю Bag, милый!
Волшебная Урна Осьминога

2

Утилиты Bash + GNU, 71 61

sort|uniq -c|sort -nr|awk '{printf$1-a?"\n%d":",%d",$2;a=$1}'

Ввод в виде списка с разделителями новой строки. Вывести как разделенный новой строкой список значений, разделенных запятыми.

Попробуйте онлайн .


2

MATL , 9 байт

9B#uw3XQP

Ввод - это вектор-столбец, использующий в ;качестве разделителя.

Попробуйте онлайн!

объяснение

9B#u   % Call 'unique' function with first and fourth outputs: unique entries and
       % number of occurrences
w      % Swap
3XQ    % Call 'accumarray' with anonymous function @(x){sort(x).'}. The output is
       % a cell array with the elements of the input grouped by their frequency.
       % Cells are sorted by increasing frequency. Some cells may be empty, but
       % those won't be displayed
P      % Flip cell array, so that groups with higher frequency appear first.
       % Implicitly display

2

k, 22 байта

{x@!x}{(>x)@=x@>x}#:'=

Попробуйте онлайн.

( AW, кажется, требует дополнительного@ перед #, но OK не делает.)

Объяснение:

                     = /group identical numbers in a map/dict
                  #:'  /get number of times each number is repeated
                       /this is almost the answer, but without the inner lists
      {      x@>x}     /order "number of times" greatest to least
            =          /group them (to make the smaller groups)
       (>x)@           /get the actual numbers into place
{x@!x}                 /get values of the map/dict it's in

github.com/JohnEarnest/ok для всех, кто интересуется, что kэто такое на самом деле ok. Ба-дум-цсссс ...
Волшебная урна осьминога


2

Mathematica, 79 байтов

Table[#&@@@f[[i]],{i,Length[f=GatherBy[Sort[Tally@#,#1[[2]]>#2[[2]]&],Last]]}]&

вход

[{1, 1, 1, 4, 5, 6, 6, 6, 7, 7, 8, 8, 8, 8, 8, 8, 8, 9, 5, 6, 5, 6, 5, 6, 5, 6, -56}]

выход

{{8, 6}, {5}, {1}, {7}, {-56, 9, 4}}


The GatherBy я упомянул Мартину! Я задавался вопросом, как это будет сделано :).
Волшебная Урна Осьминога

Sort[...,...&]это просто SortBy[...,-Last@#&].
Мартин Эндер

Length[f=...], И First/@есть #&@@@.
Мартин Эндер

исправлено, исправлено и исправлено
J42161217

2

R , 84 77 байт

-7 байт благодаря mb7744

unique(lapply(x<-sort(table(scan()),T),function(y)as.double(names(x[x==y]))))

Читает со стандартного ввода; возвращает список с подвекторами целых чисел в возрастающем порядке. Если бы мы могли возвращать строки вместо целых, то я мог бы отбросить 11 байтов (удаляя вызов as.double), но это все. tableФункция R выполняет здесь тяжелую работу, подсчитывая вхождения каждого члена своего ввода; затем он объединяет их по количеству (names ). Конечно, это строка, поэтому мы должны привести ее к целому числу / двойному.

Попробуйте онлайн!


Вы можете потерять 7 байт, исключив «который» и используя логическое индексирование
mb7744

@ mb7744 о, черт.
Джузеппе

1
Я сделал еще один удар по R. Сожалею, как долго длится лямбда-синтаксис, поэтому я попытался избежать этого. Взамен мне пришлось использовать вложенные lapply, но, по крайней мере, в этом случае я могу назначить короткую переменную lapply. Я не могу назначить переменную для функции function...
mb7744

2

JavaScript (ES6), 100 98 96 93 байта

Благодаря @Neil удалось сэкономить 2 байта (плюс он исправил ошибку в моем случае). Сохранено еще 3 байта благодаря @TomasLangkaas.

a=>a.sort().map((_,n)=>a.filter((v,i)=>i-a.indexOf(v)==n&v!=a[i+1])).filter(a=>a+a).reverse()

Контрольные примеры

f=
a=>a.sort().map((_,n)=>a.filter((v,i)=>i-a.indexOf(v)==n&v!=a[i+1])).filter(a=>a+a).reverse()

console.log(JSON.stringify(f([1,2,3])))
console.log(JSON.stringify(f([1,1,1,2,2,3,3,4,5,6])))
console.log(JSON.stringify(f([1,1,1,4,5,6,6,6,7,7,8,8,8,8,8,8,8,9,5,6,5,6,5,6,5,6,-56])))
console.log(JSON.stringify(f([])))


Ваш тест испорчен (не работает на ноль) , но я думаю , что вы все еще можете сохранить байты путем фильтрации и реверсирования вместо unshifting: a=>a.sort().map((_,n)=>a.filter((v,i)=>i-a.indexOf(v)==n&v!=a[i+1])).filter(a=>1/a[0]).reverse().
Нил

Ааа, я должен был знать, чтобы проверить на 0! Ваш код исправляет это, плюс он короче, так что спасибо вам за это
Рик Хичкок

Сохраните еще 3 байта, изменив .filter(a=>1/a[0])на.filter(a=>''+a) .
Томас Лангкаас

Хороший, @TomasLangkaas, спасибо. (Сохраняет 2 байта.)
Рик Хичкок

Мой плохой (есть проблемы со счетом), но .filter(a=>a+a)предоставит дополнительный байт.
Томас Лангкас

1

V , 60 , 54 байта

Úòͨ¼¾©î±/± ±òHòø 
pkJjòú!
Ǩ^ƒ ©î±/o
Îf ld|;D
òV{Jk

Попробуйте онлайн!

HexDump:

00000000: daf2 cda8 bc81 bea9 eeb1 2fb1 20b1 f248  ........../. ..H
00000010: f2f8 200a 706b 4a6a f2fa 210a c7a8 5e83  .. .pkJj..!...^.
00000020: 20a9 81ee b12f 6f0a ce66 206c 647c 3b44   ..../o..f ld|;D
00000030: 0af2 567b 4a6b                           ..V{Jk

Как бы я ни любил V, я уверен, что это худший язык для этой задачи. Особенно учитывая, что он не поддерживает списки и, в основном, не поддерживает числа. Просто струнная манипуляция.


1

C #, 119 байт

Просто быстрый удар в это:

using System.Linq;
a=>a.GroupBy(x=>x)
    .GroupBy(x=>x.Count(),x=>x.Key)
    .OrderBy(x=>-x.Key)
    .Select(x=>x.ToArray())
    .ToArray()

2
+1 Вы можете удалить System.Func<int[],int[][]>F=и трейлинг, ;хотя. Это не является частью подсчета байтов для такого рода лямбд.
Кевин Круйссен

@KevinCruijssen, я понятия не имел. Благодарность!
Hand-E-Food

1

R , 66 байт

(l=lapply)(l(split(x<-table(scan()),factor(-x)),names),as.integer)

Попробуйте онлайн!

Если в выходных данных целые числа могут быть в строковом формате, они могут уменьшиться до 48 байт (как упомянуто в ответе @ Giuseppe).


Ungolfed:

input <- scan(); # read input
x <- table(input); # count how many times each integer appears, in a named vector
y <- split(x, factor(-x)) # split the count into lists in increasing order
z <- lapply(y, names) # access the the original values which are still
                      # attached via the names
lapply(z, as.integer) # convert the names back to integers

as.doubleкороче на один байт, и он должен работать так же, какas.integer
Джузеппе

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

1

PowerShell, 77, 70 байт

($a=$args)|group{($a-eq$_).count}|sort n* -Des|%{,($_.group|sort -u)}

NB. Чтобы убедиться, что эти результаты правильно сгруппированы (поскольку визуально нет разграничения между содержимым каждого массива), вы можете добавить | write-hostв конец строки выше.

Подтверждения

Благодаря:

  • TessellatingHeckler для экономии 7 байт путем масштабного рефакторинга / переписывания для более подходящего подхода.

предыдущий

77 байт

param($x)$x|group|sort count -desc|group count|%{,($_.group|%{$_.group[0]})}

Здорово спасибо Мне пришлось включить ,()для группировки (так как вывод только показывал как один непрерывный массив). Это гораздо больше игры в гольф, чем моя первоначальная попытка; потрясающая работа!
JohnLBevan

0

Groovy, 71 байт

{a->a.groupBy{a.count(it)}.sort{-it.key}.values().collect{it.unique()}}

Я на самом деле только что узнал о groupBy после создания этого. Я не знал, что коллекционирование было не единственным моим выбором.


{
    a->                 // [1,2,1,2,3,3,3,6,5,4]
    a.groupBy{      
        a.count(it)     // [2:[1,2,1,2],3:[3,3,3],1:[6,5,4]]
    }.sort{             
        -it.key         // [3:[3,3,3],2:[1,2,1,2],1:[6,5,4]]
    }.values().collect{ // [[3,3,3],[1,2,1,2],[6,5,4]]
        it.unique()
    }                   // [[3],[1,2],[6,5,4]]
}

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.