Grouper une liste par fréquence


26

Étant donné une liste d'entiers, groupez les éléments qui se produisent le plus en premier, puis regroupez les suivants et ainsi de suite jusqu'à ce que chaque élément unique de la liste ait été groupé une fois.


Exemples:

Contribution: [1,2,3]

Sortie: [[1,2,3]]


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

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


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

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


Contribution: []

Sortie: []


Contribution: (empty input)

Sortie: ERROR/Undefined/Doesn't matter


Règles

  • Les groupements doivent passer de la fréquence maximale à la fréquence minimale.
  • L'ordre interne des regroupements est arbitraire (par exemple, l'exemple 3 pourrait [8,6] place).
  • Il s'agit du , le plus petit nombre de victoires d'octets.

en relation


1
La sortie peut-elle être au format chaîne? C'est à dire. Une liste de listes, mais chaque nombre représenté par un caractère au lieu d'un entier.
mb7744

Réponses:



7

Mathematica, 43 octets

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

Essayez-le en ligne! (Utilisation des mathématiques.)

Alternativement:

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

5
Il n'y a pas intégré?
Magic Octopus Urn

Est GatherByune option, pas sûr car je ne connais pas la langue.
Magic Octopus Urn

1
@carusocomputing Il trie les groupes en fonction de la première occurrence des éléments dans la liste d'origine, il me faudrait donc toujours trier les groupes par la suite. En triant d'abord la liste, je peux enregistrer un octet avec SplitBy(cela SortByserait également plus compliqué si je le faisais en GatherBypremier).
Martin Ender

Intéressant, donc le "doit être en ordre du maximum au minimum" gâche ça?
Magic Octopus Urn

@carusocomputing Exactement.
Martin Ender

5

Python 2 , 145 141 octets

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

Essayez-le en ligne!

Ceci est ma première soumission après des années de lecture.

En gros, il place tous les éléments dans un compteur (dictionnaire du nombre de chaque élément de la liste) et .most_common () place les éléments dans l'ordre de fréquence décroissant. Après cela, il suffit de formater les éléments dans la bonne liste.

4 octets enregistrés grâce aux ovs .


4
Bienvenue chez PPCG :). Ne soyez pas aussi accro que moi.
Magic Octopus Urn

La création de votre propre fonction itemgetter est plus courte de 4 octets que son importation:o=lambda n:lambda l:l[n]
ovs

5

JavaScript (ES6), 95 101 octets

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)

Comment?

Pour chaque élément x du tableau d'entrée a , nous calculons le nombre n d'éléments de a différents de x :

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

Nous utilisons les indices n et x pour remplir le tableau o :

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

Edit : Parce que JS ne prend pas en charge les indices de tableau négatifs, nous avons besoin de la formule x * x + (x > 0)pour forcer les indices positifs.

Cela nous donne un tableau de tableaux contenant les éléments uniques de la liste d'origine, regroupés par fréquence et classés du plus fréquent au moins fréquent.

Cependant, le tableau externe et les tableaux internes ont potentiellement de nombreux emplacements vides que nous voulons filtrer. Nous le faisons avec la fonction F , appliquée à o et à chacun de ses éléments:

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

Cas de test


Je pense que Setvous permet d' économiser un octet: 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 C'est assez différent de mon approche actuelle. Peut-être devriez-vous l'afficher en tant que nouvelle réponse?
Arnauld

Je ne pensais pas que passer o[n]d'un tableau à un ensemble était si différent, mais j'ai déjà joué à la réponse de @ RickHitchcock de toute façon, il n'y a donc pas grand-chose.
Neil



2

Clojure, 74 octets

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

Semble assez verbeux: /


Battez-moi (et battez-moi de quelques octets, utilisation intelligente de la comp -marche arrière!). Pas aussi court que les autres langues, mais j'ai trouvé ça amusant car Clojure a intégré le "group-by" et les "fréquences".
MattPutnam

Quand j'ai lu la description de la tâche, j'espérais 50 ou 60 octets, mais l'implémentation s'est avérée un peu plus délicate.
NikoNyrh

2

Perl 6 , 43 octets

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

Essaye-le

Étendu:

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

Wow, j'oublie toujours Bag, chouette!
Magic Octopus Urn

2

Utilitaires Bash + GNU, 71 61

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

Entrez en tant que liste délimitée par des sauts de ligne. Sortie sous forme de liste délimitée par des sauts de ligne de valeurs séparées par des virgules.

Essayez-le en ligne .


2

MATL , 9 octets

9B#uw3XQP

L'entrée est un vecteur de colonne, utilisé ;comme séparateur.

Essayez-le en ligne!

Explication

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 octets

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

Essayez-le en ligne.

( AW's k semble nécessiter un supplément @avant le #, mais oK ne le fait pas.)

Explication:

                     = /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 pour quiconque se demande ce que kc'est, c'est en fait ok. Ba-dum-tssss ...
Urne de poulpe magique

2

Brachylog , 10 octets

ọtᵒ¹tᵍhᵐ²|

Essayez-le en ligne!

Explication

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 octets

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

contribution

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

sortie

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


Le GatherBy que j'ai mentionné à Martin! Je me demandais comment cela se ferait :).
Magic Octopus Urn

Sort[...,...&]est juste SortBy[...,-Last@#&].
Martin Ender

Length[f=...]. Et First/@c'est #&@@@.
Martin Ender

fixe, fixe et fixe
J42161217

2

R , 84 77 octets

-7 octets grâce à mb7744

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

Lit à partir de stdin; renvoie une liste avec des sous-vecteurs d'entiers dans l'ordre croissant. Si nous pouvions renvoyer des chaînes au lieu d'entiers, je pourrais supprimer 11 octets (supprimer l'appel à as.double), mais c'est à peu près tout. La tablefonction de R fait le gros du travail ici, en comptant les occurrences de chaque membre de son entrée; puis il les agrège par count ( names). Bien sûr, c'est une chaîne, nous devons donc la contraindre à un entier / double.

Essayez-le en ligne!


Vous pouvez perdre 7 octets en éliminant le "qui" et en utilisant l'indexation logique
mb7744

@ mb7744 oh duh.
Giuseppe

1
J'ai essayé de nouveau avec R. Il est malheureux de savoir combien de temps la syntaxe lambda est, alors j'ai décidé d'essayer de l'éviter. En échange, j'ai dû utiliser des imbriqués lapply, mais au moins dans ce cas, je peux assigner une variable courte à lapply. Je n'arrive pas à assigner une variable à la fonction function...
mb7744

2

JavaScript (ES6), 100 98 96 93 octets

Enregistré 2 octets grâce à @Neil (en plus, il a corrigé un bug de bord-cas dans mon code). Sauvegardé 3 octets supplémentaires grâce à @TomasLangkaas.

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

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


Votre test est défectueux (ne fonctionne pas pour zéro) mais je pense que vous pouvez encore économiser des octets en filtrant et en inversant au lieu 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, j'aurais dû savoir tester pour 0! Votre code le corrige, plus il est plus court, alors merci pour cela
:)

Économisez 3 octets supplémentaires en passant .filter(a=>1/a[0])à .filter(a=>''+a).
Tomas Langkaas

Bien joué, @TomasLangkaas, merci. (Enregistre 2 octets.)
Rick Hitchcock

Mon mauvais (avoir du mal à compter), mais .filter(a=>a+a)fournirait l'octet supplémentaire.
Tomas Langkaas

1

V , 60 , 54 octets

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

Essayez-le en ligne!

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

Autant que j'aime V, je suis presque sûr que c'est le pire langage possible pour la tâche. Surtout si l'on considère qu'il n'a pas de support pour les listes, et fondamentalement pas de support pour les nombres. Manipulation de chaîne juste.


1

C #, 119 octets

Juste un coup d'œil rapide:

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 You can remove the System.Func<int[],int[][]>F= and trailing ; though. That isn't part of the byte-count for these kind of lambdas.
Kevin Cruijssen

@KevinCruijssen, I had no idea. Thanks!
Hand-E-Food

1

R, 66 bytes

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

Try it online!

If in the output the integers may be in string format, can drop to 48 bytes (as mentioned in @Giuseppe's answer).


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 is shorter by one byte, and it should work the same as as.integer
Giuseppe

Well, it depends whether you want to return an integer or a double. If double is okay, maybe character would be as well, and we could both save some bytes.
mb7744

1

PowerShell, 77, 70 bytes

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

NB: To see that these results are correctly grouped (since visually there's no deliniation between the contents of each array), you may wish to append | write-host to the end of the above line.

Acknowledgements

Thanks to:

  • TessellatingHeckler for saving 7 bytes by massively refactoring / rewriting to a way more golfed approach.

Previous

77 bytes

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

Bien, merci. J'ai dû inclure le ,()regroupement (car la sortie ne montrait que comme un tableau continu). C'est bien plus golfique que ma tentative originale; super travail!
JohnLBevan

0

Groovy, 71 octets

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

En fait, je viens d'apprendre sur groupBy après avoir créé cela. Je ne savais pas que collecter n'était pas mon seul choix.


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

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.