Agrupar una lista por frecuencia


26

Dada una lista de enteros, agrupe los elementos que ocurren más primero, luego agrupe los siguientes y así sucesivamente hasta que cada elemento único en la lista se haya agrupado una vez.


Ejemplos:

Entrada: [1,2,3]

Salida: [[1,2,3]]


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

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


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

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


Entrada: []

Salida: []


Entrada: (empty input)

Salida: ERROR/Undefined/Doesn't matter


Reglas

  • Las agrupaciones deben ir de frecuencia máxima a frecuencia mínima.
  • El orden interno de las agrupaciones es arbitrario (por ejemplo, el ejemplo 3 podría tener [8,6] ).
  • Este es el , el menor recuento de bytes gana.

Relacionado


1
¿Puede la salida estar en formato de cadena? Es decir. Una lista de listas, pero cada número representado por un carácter en lugar de un entero.
mb7744

Respuestas:



7

Mathematica, 43 bytes

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

Pruébalo en línea! (Usando matemáticas).

Alternativamente:

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

55
No hay incorporado?
Magic Octopus Urn

Es GatherByuna opción, no estoy seguro porque no sé el idioma.
Magic Octopus Urn

1
@carusocomputing Ordena los grupos por la primera aparición de los elementos en la lista original, por lo que aún tendría que ordenar los grupos después. Al ordenar la lista primero, puedo guardar un byte con SplitBy(también SortBysería realmente más complicado si lo hiciera GatherByprimero).
Martin Ender

Interesante, ¿entonces el "debe estar en orden de máximo a mínimo" lo arruina?
Magic Octopus Urn

@carusocomputing Exactamente.
Martin Ender

5

Python 2 , 145 141 bytes

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

Pruébalo en línea!

Esta es mi primera presentación después de años de lectura.

Básicamente, pone todos los elementos en un contador (diccionario de cuántos elementos de cada uno de la lista) y .most_common () pone los elementos en orden de frecuencia descendente. Después de eso, solo es cuestión de formatear los elementos en la lista correcta.

Guardado 4 bytes gracias a los ovs .


44
Bienvenido a PPCG :). No te vuelvas tan adicto como yo.
Magic Octopus Urn

Crear su propia función itemgetter es 4 bytes más corto que importarlo:o=lambda n:lambda l:l[n]
2017

5

JavaScript (ES6), 95 101 bytes

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)

¿Cómo?

Para cada elemento x de la matriz de entrada a , calculamos el número n de elementos de a que son diferentes de x :

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

Usamos los índices n y x para llenar la matriz o :

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

Editar : Debido a que JS no admite índices de matriz negativos, necesitamos la fórmula x * x + (x > 0)para forzar índices positivos.

Esto nos da una serie de matrices que contienen los elementos únicos de la lista original, agrupados por frecuencia y ordenados de más frecuentes a menos frecuentes.

Sin embargo, tanto la matriz externa como la matriz interna potencialmente tienen muchas ranuras vacías que queremos filtrar. Hacemos esto con la función F , aplicada a o y cada uno de sus elementos:

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

Casos de prueba


Creo que Setahorra más de 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 Esto es bastante diferente de mi enfoque actual. ¿Tal vez deberías publicarlo como una nueva respuesta?
Arnauld

No pensé que cambiar o[n]de una matriz a un conjunto fuera tan diferente, pero de todos modos jugué la respuesta de @ RickHitchcock de todos modos, así que no tiene mucho sentido.
Neil



2

Clojure, 74 bytes

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

Parece bastante detallado: /


Gáneme a eso (y báteme por unos pocos bytes, ¡uso inteligente de comp -revertir!). No es tan corto como otros idiomas, pero pensé que era divertido ya que tiene Clojure "grupo-by" y "frecuencias" incorporados.
MattPutnam

Cuando leí la descripción de la tarea esperaba 50 o 60 bytes, pero la implementación real resultó ser un poco más complicada.
NikoNyrh

2

Perl 6 , 43 bytes

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

Pruébalo

Expandido:

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

¡Guau, siempre me olvido de la Bagbuena!
Magic Octopus Urn

2

Bash + GNU utilidades, 71 61

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

Ingrese como una lista delimitada por nueva línea. Salida como una lista delimitada por nueva línea de valores separados por comas.

Pruébalo en línea .


2

MATL , 9 bytes

9B#uw3XQP

La entrada es un vector de columna, que se usa ;como separador.

Pruébalo en línea!

Explicación

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 bytes

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

Pruébalo en línea.

( La k de AW parece requerir un extra@ antes que el #, pero OK no)

Explicación:

                     = /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 para cualquiera que se pregunte qué kes, en realidad es ok. Ba-dum-tssss ...
Urna de pulpo mágico

2

Brachylog , 10 bytes

ọtᵒ¹tᵍhᵐ²|

Pruébalo en línea!

Explicación

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 bytes

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

entrada

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

salida

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


The Gather ¡Por lo que le mencioné a Martin! Me preguntaba cómo se haría esto :).
Magic Octopus Urn

Sort[...,...&]es justo SortBy[...,-Last@#&].
Martin Ender

Length[f=...]. Y First/@es #&@@@.
Martin Ender

fijo, fijo y fijo
J42161217

2

R , 84 77 bytes

-7 bytes gracias a mb7744

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

Lee de stdin; devuelve una lista con subvectores de enteros en orden creciente. Si pudiéramos devolver cadenas en lugar de ints, podría eliminar 11 bytes (eliminando la llamada a as.double), pero eso es todo. La tablefunción de R hace el trabajo pesado aquí, contando las ocurrencias de cada miembro de su entrada; luego los agrega por count ( names). Por supuesto, es una cadena, por lo que tenemos que obligarla a un entero / doble.

Pruébalo en línea!


Puede perder 7 bytes eliminando el "cual", y usando indexación lógica
mb7744

@ mb7744 oh duh.
Giuseppe

1
Le di otra puñalada con R. Es lamentable la duración de la sintaxis lambda, así que me puse a tratar de evitarla. A cambio, tuve que usar anidados lapply, pero al menos en ese caso puedo asignar una variable corta a lapply. Parece que no puedo asignar una variable a la función function...
mb7744

2

JavaScript (ES6), 100 98 96 93 bytes

Ahorré 2 bytes gracias a @Neil (además corrigió un error de caso de borde en mi código). Ahorré 3 bytes más gracias 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()

Casos de prueba

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


Su prueba es defectuoso (no funciona para el cero), pero creo que todavía se puede guardar bytes mediante el filtrado y la inversión en lugar de 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, debería haber sabido probar para 0! Su código lo corrige, además es más corto, así que gracias por eso
Rick Hitchcock

Ahorre 3 bytes más cambiando .filter(a=>1/a[0])a .filter(a=>''+a).
Tomas Langkaas

Buena, @TomasLangkaas, gracias. (Ahorra 2 bytes.)
Rick Hitchcock

Lo malo (tengo problemas para contar), pero .filter(a=>a+a)proporcionaría el byte adicional.
Tomas Langkaas

1

V , 60 , 54 bytes

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

Pruébalo en línea!

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

Por mucho que amo a V, estoy bastante seguro de que este es el peor lenguaje posible para la tarea. Especialmente considerando que no tiene soporte para listas, y básicamente no tiene soporte para números. Solo manipulación de cuerdas.


1

C #, 119 bytes

Solo una puñalada rápida:

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 Sin embargo, puedes eliminar el System.Func<int[],int[][]>F=y el final ;. Eso no es parte del conteo de bytes para este tipo de lambdas.
Kevin Cruijssen

@KevinCruijssen, no tenía idea. ¡Gracias!
Hand-E-Food

1

R , 66 bytes

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

Pruébalo en línea!

Si en la salida los enteros pueden estar en formato de cadena, pueden caer a 48 bytes (como se menciona en la respuesta de @ Giuseppe).


Sin golf:

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.doublees más corto en un byte, y debería funcionar igual queas.integer
Giuseppe

Bueno, depende de si quieres devolver un número entero o un doble. Si double está bien, quizás el carácter también lo sea, y ambos podríamos guardar algunos bytes.
mb7744

1

Potencia Shell, 77, 70 bytes

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

NB: Para ver que estos resultados están agrupados correctamente (ya que visualmente no hay delincuencia entre los contenidos de cada matriz), puede agregar | write-hostal final de la línea anterior.

Expresiones de gratitud

Gracias a:

  • TessellatingHeckler para ahorrar 7 bytes refactorizando / reescribiendo masivamente a un enfoque mucho más complejo.

Anterior

77 bytes

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

Genial gracias. Tuve que incluir el ,()para la agrupación (ya que la salida solo se mostraba como una matriz continua). Esto es mucho más golfístico que mi intento original; ¡impresionante trabajo!
JohnLBevan

0

Groovy, 71 bytes

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

De hecho, acabo de enterarme de groupBy después de crear esto. No sabía que cobrar no era mi única opción.


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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.