Raggruppa un elenco per frequenza


26

Dato un elenco di numeri interi, raggruppa gli elementi che si verificano per primi, quindi raggruppa il successivo e così via fino a quando ogni elemento univoco nell'elenco non è stato raggruppato una volta.


Esempi:

Ingresso: [1,2,3]

Produzione: [[1,2,3]]


Ingresso: [1,1,1,2,2,3,3,4,5,6]

Produzione: [[1],[2,3],[4,5,6]]


Ingresso: [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]

Produzione: [[6, 8],[5],[1],[7],[9,4,-56]]


Ingresso: []

Produzione: []


Ingresso: (empty input)

Produzione: ERROR/Undefined/Doesn't matter


Regole

  • I raggruppamenti devono andare dalla frequenza massima alla frequenza minima.
  • L'ordine interno dei raggruppamenti è arbitrario (invece l'esempio 3 potrebbe avere [8,6]).
  • Questo è , vince il conteggio di byte più basso.

Relazionato


1
L'output può essere in formato stringa? Vale a dire. Un elenco di elenchi, ma ogni numero rappresentato da un carattere anziché da un numero intero.
mb7744,

Risposte:



7

Mathematica, 43 byte

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

Provalo online! (Usando la matematica.)

In alternativa:

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

5
Non è integrato?
Magic Octopus Urn,

È GatherByun'opzione, non sono sicuro perché non conosco la lingua.
Magic Octopus Urn,

1
@carusocomputing Ordina i gruppi in base alla prima occorrenza degli elementi nell'elenco originale, quindi dovrei comunque ordinare i gruppi in seguito. Ordinando prima l'elenco, posso salvare un byte con SplitBy(inoltre SortBysarebbe effettivamente più complicato se lo facessi GatherByprima).
Martin Ender,

Interessante, quindi il "deve essere in ordine dal massimo al minimo" rovina tutto?
Magic Octopus Urn,

@carusocomputing Esatto.
Martin Ender,

5

Python 2 , 145 141 byte

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))]

Provalo online!

Questa è la mia prima presentazione dopo anni di lettura.

Fondamentalmente mette tutti gli elementi in un contatore (dizionario di quanti di ciascun elemento nell'elenco) e .most_common () mette gli elementi in ordine decrescente di frequenza. Dopodiché, si tratta solo di formattare gli elementi nell'elenco giusto.

Salvato 4 byte grazie a ovs .


4
Benvenuto in PPCG :). Non diventare dipendente come me.
Magic Octopus Urn,

La creazione della tua funzione itemgetter è più corta di 4 byte rispetto all'importazione:o=lambda n:lambda l:l[n]
ovs

5

JavaScript (ES6), 95 101 byte

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)

Come?

Per ogni elemento x dell'array di input a , calcoliamo il numero n di elementi di a che sono diversi da x :

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

Usiamo gli indici n e x per riempire l'array o :

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

Modifica : poiché JS non supporta indici di array negativi, abbiamo bisogno della formula x * x + (x > 0)per forzare indici positivi.

Questo ci offre una serie di array contenenti gli elementi univoci della lista originale, raggruppati per frequenza e ordinati dal più frequente al meno frequente.

Tuttavia, sia l'array esterno che quello interno hanno potenzialmente molti slot vuoti che vogliamo filtrare. Lo facciamo con la funzione F , applicata a o e ciascuno dei suoi elementi:

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

Casi test


Penso che un Setpuoi risparmiare un byte: 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,

@Neil Questo è abbastanza diverso dal mio attuale approccio. Forse dovresti pubblicarlo come una nuova risposta?
Arnauld,

Non pensavo che passare o[n]da un array a un set fosse così diverso, ma ho già giocato a golf con la risposta di @ RickHitchcock comunque, quindi non ha molto senso.
Neil,



2

Clojure, 74 byte

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

Sembra abbastanza prolisso: /


Sconfiggimi (e picchiami di qualche byte, uso intelligente comp -per invertire!). Non così breve come altre lingue, ma ho pensato che fosse divertente dato che Clojure ha "raggruppamento" e "frequenze" integrate.
MattPutnam,

Quando ho letto la descrizione dell'attività speravo in 50 o 60 byte, ma l'implementazione effettiva si è rivelata un po 'più complicata.
NikoNyrh,

2

Perl 6 , 43 byte

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

Provalo

Allargato:

*                   # 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])

Caspita, mi dimentico sempre Bag, bello!
Magic Octopus Urn,

2

Utilità Bash + GNU, 71 61

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

Input come un elenco delimitato da nuova riga. Output come un elenco delimitato da nuova riga di valori separati da virgola.

Provalo online .


2

MATL , 9 byte

9B#uw3XQP

L'input è un vettore di colonna, che utilizza ;come separatore.

Provalo online!

Spiegazione

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 byte

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

Provalo online.

( La k di AW sembra richiedere un extra @prima di #, ma oK no.)

Spiegazione:

                     = /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 per chiunque si chieda cosa ksia, in realtà è ok. Ba-dum-tssss ...
Magic Octopus Urn

2

Brachylog , 10 byte

ọtᵒ¹tᵍhᵐ²|

Provalo online!

Spiegazione

Example input: [2,1,1,3]

ọ            Occurences:            [[2,1],[1,2],[3,1]]
 tᵒ¹         Order desc. by tail:   [[1,2],[3,1],[2,1]]
    tᵍ       Group by tail:         [[[1,2]],[[3,1],[2,1]]]
      hᵐ²    Map twice head:        [[1],[3,2]]

         |   Else (Input = [])      Input = Output

2

Mathematica, 79 byte

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

ingresso

[{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}]

produzione

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


The GatherBy di cui ho parlato con Martin! Mi chiedevo come sarebbe stato fatto :).
Magic Octopus Urn,

Sort[...,...&]è giusto SortBy[...,-Last@#&].
Martin Ender,

Length[f=...]. Ed First/@è #&@@@.
Martin Ender,

fisso, fisso e fisso
J42161217

2

R , 84 77 byte

-7 byte grazie a mb7744

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

Legge da stdin; restituisce un elenco con sottovettori di numeri interi in ordine crescente. Se potessimo restituire stringhe invece di ints, allora potrei rilasciare 11 byte (rimuovendo la chiamata a as.double), ma questo è tutto. La tablefunzione di R fa il sollevamento pesante qui, contando le occorrenze di ciascun membro del suo input; quindi li aggrega per count ( names). Certo, questa è una stringa, quindi dobbiamo costringerla a un numero intero / doppio.

Provalo online!


Puoi perdere 7 byte eliminando il "quale" e utilizzando l'indicizzazione logica
mb7744

@ mb7744 oh duh.
Giuseppe,

1
Ho preso un'altra pugnalata con R. È sfortunato quanto sia lunga la sintassi lambda, quindi ho deciso di evitare. In cambio ho dovuto usare quelli nidificati lapply, ma almeno in quel caso posso assegnare una breve variabile a lapply. Non riesco ad assegnare una variabile alla funzione function...
mb7744

2

JavaScript (ES6), 100 98 96 93 byte

Salvato 2 byte grazie a @Neil (in più ha risolto un bug del caso limite nel mio codice). Salvati altri 3 byte grazie a @TomasLangkaas.

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

Casi test

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([])))


Il test è viziata (non funziona per lo zero), ma penso che si può ancora salvare byte filtrando e invertendo invece di 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().
Neil,

Ahh, avrei dovuto sapere di provare per 0! Il tuo codice lo risolve, inoltre è più breve, quindi grazie per quello
:)

Salva altri 3 byte cambiando .filter(a=>1/a[0])in .filter(a=>''+a).
Tomas Langkaas,

Bello, @TomasLangkaas, grazie. (Salva 2 byte.)
Rick Hitchcock,

Mio male (ho problemi con il conteggio), ma .filter(a=>a+a)fornirebbe il byte in più.
Tomas Langkaas,

1

V , 60 , 54 byte

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

Provalo online!

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

Per quanto io ami V, sono abbastanza sicuro che questa sia la peggior lingua possibile per l'attività. Soprattutto se si considera che non ha supporto per gli elenchi e sostanzialmente nessun supporto per i numeri. Solo manipolazione di stringhe.


1

C #, 119 byte

Solo una rapida pugnalata:

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 È possibile rimuovere il System.Func<int[],int[][]>F=e trailing ;comunque. Questo non fa parte del conteggio dei byte per questo tipo di lambda.
Kevin Cruijssen,

@KevinCruijssen, non ne avevo idea. Grazie!
Hand-E-Food,

1

R , 66 byte

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

Provalo online!

Se nell'output gli interi possono essere in formato stringa, possono scendere a 48 byte (come indicato nella risposta di @ 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è più corto di un byte e dovrebbe funzionare comeas.integer
Giuseppe,

Bene, dipende se si desidera restituire un numero intero o un doppio. Se il doppio va bene, forse lo sarebbe anche il personaggio e potremmo salvare entrambi dei byte.
mb7744,

1

PowerShell, 77, 70 byte

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

NB: Per vedere che questi risultati sono correttamente raggruppati (dal momento che visivamente non c'è delineamento tra i contenuti di ciascun array), potresti voler aggiungere | write-hostalla fine della riga sopra.

Ringraziamenti

Grazie a:

  • TessellatingHeckler per il salvataggio di 7 byte mediante il refactoring / riscrittura massiccia di un approccio più golfizzato.

Precedente

77 byte

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

Bene grazie. Ho dovuto includere il ,()raggruppamento per (dal momento che l'output mostrava solo un array continuo). Questo è molto più goloso del mio tentativo originale; lavoro fantastico!
JohnLBevan,

0

Groovy, 71 byte

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

In realtà ho appena imparato a conoscere GroupBy dopo averlo creato. Non sapevo che collezionare non fosse la mia unica scelta.


{
    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]]
}

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.