Comptez les mots dans un texte et affichez-les

26

Le code doit prendre en entrée un texte (non obligatoire peut être n'importe quoi fichier, stdin, chaîne pour JavaScript, etc.):

This is a text and a number: 31.

La sortie doit contenir les mots avec leur nombre d'occurrences, triés par le nombre d'occurrences dans l'ordre décroissant:

a:2
and:1
is:1
number:1
This:1
text:1
31:1

Notez que 31 est un mot, donc un mot est quelque chose d'alpha-numérique, le nombre n'agit pas comme des séparateurs donc par exemple se 0xAFqualifie comme un mot. Les séparateurs seront tout ce qui n'est pas alphanumérique, y compris .(point) et -(trait d'union), i.e.ou pick-me-updonnerait respectivement 2 ou 3 mots. Devrait être sensible à la casse, Thiset thisserait deux mots différents, 'serait également séparateur ainsi wouldnet tsera 2 mots différents dewouldn't .

Écrivez le code le plus court dans la langue de votre choix.

Réponse correcte la plus courte à ce jour:

Eduard Florinescu
la source
5
Le cas est-il important (c'est-à-dire Thisle même que thiset tHIs)?
Gareth
Si un élément non alphanumérique compte comme séparateur, est-ce que wouldn't2 mots ( wouldnet t)?
Gareth
@Gareth Doit être sensible à la casse, Thiset thisserait en effet deux mots différents, identiques wouldnet t.
Eduard Florinescu
Si ce ne serait pas 2 mots, ne devrait-il pas être "voudrait" et "nt" puisque son abréviation pour ne le serait pas, ou est-ce trop grammatical nazi-ish?
Teun Pronk
@TeunPronk J'essaie de rester simple, mettre quelques règles encouragera les exceptions à être en ordre avec la grammaire, et il y a beaucoup d'exceptions là-bas.Ex en anglais i.e.est un mot mais si nous laissons le point tous les points à la fin des phrases seront prises, même avec des guillemets ou des guillemets simples, etc.
Eduard Florinescu

Réponses:

27

grep et coreutils  44  42

grep -io '[a-z0-9]*'|sort|uniq -c|sort -nr

Tester:

printf "This is a text and a number: 31." |
grep -io '[a-z0-9]*'|sort|uniq -c|sort -nr

Résulte en:

  2 a
  1 This
  1 text
  1 number
  1 is
  1 and
  1 31

Mise à jour

  • Utilisez l'option insensible à la casse et l'expression régulière plus courte. Merci Tomas.
Thor
la source
2
Ceci est presque exactement la réponse de McEllroy au livre de Knuth Literate Programming . La seule différence étant que cela n'inclut pas de tuyau headà la fin.
AJMansfield
C'était à peu près ma première pensée aussi.
Rob
1
'\ W +' ne fonctionnerait-il pas aussi?
Sylwester
1
41 personnages :grep -io \[A-Z0-9]*|sort|uniq -c|sort -nr
Tomas
1
@Tomas: Ajouté ceci à la réponse, merci. Je suis parti en protection pour l'astérisque, car il développait les noms de fichiers dans certains shells.
Thor
18

Java 8: 289

Ce qui est plutôt bien, car java est une langue très non golfique.

import java.util.stream.*;class C{static void main(String[]a){Stream.of(a).flatMap(s->of(s.split("[\\W_]+"))).collect(Collectors.groupingBy(x->x,Collectors.counting())).entrySet().stream().sorted(x,y->x.getValue()-y.getValue()).forEach(e->System.out.println(e.getKey()+":"+e.getValue()));}

Non golfé:

import java.util.stream.*;
class C {
    static void main(String [] args){
        Stream.of(args).flatMap(arg->Stream.of(arg.split("[\\W_]+")))
            .collect(Collectors.groupingBy(word->word,Collectors.counting()))
            .entrySet().stream().sorted(x,y->x.getValue()-y.getValue())
            .forEach(entry->System.out.println(entry.getKey()+":"+entry.getValue()));
    }
}

Exécutez à partir de la ligne de commande:

java -jar wordCounter.jar This is a text and a number: 31.
AJMansfield
la source
Regex incorrect pour le fractionnement. Cela devrait être"[^\\W_]"
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳, la String.split(String regex)méthode prend un modèle qui correspond au délimiteur à fractionner. Ainsi, par exemple, "aababba".split("b")donnerait le tableau {"aa", "a", "", "a"}. Mon expression régulière [^\\w\\d]signifie «un caractère ni dans le mot ni dans les classes de caractères numériques». [^\\W_]est à la place «un caractère qui n'est ni un trait de soulignement ni dans la classe non-caractère de mot» et correspondrait à n'importe quel caractère de mot à l'exception du trait de soulignement.
AJMansfield
Désolé, mon commentaire précédent était incorrect. \wcomprend \d, \dest donc redondant. \wcomprend un trait de soulignement, qui doit être considéré comme un séparateur selon la question. Donc, le regex correct pour le fractionnement devrait être "[\\W_]+".
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ ok, merci; J'ai résolu le problème.
AJMansfield
17

APL (57)

⎕ML←3⋄G[⍒,1↓⍉G←⊃∪↓Z,⍪+⌿∘.≡⍨Z←I⊂⍨(I←⍞)∊⎕D,⎕A,⎕UCS 96+⍳26;]

par exemple

      ⎕ML←3⋄G[⍒,1↓⍉G←⊃∪↓Z,⍪+⌿∘.≡⍨Z←I⊂⍨(I←⍞)∊⎕D,⎕A,⎕UCS 96+⍳26;]
This is a text and a number: 31.
 a       2
 This    1
 is      1
 text    1
 and     1
 number  1
 31      1

Explication:

  • ⎕D,⎕A,⎕UCS 96+⍳26: chiffres, lettres majuscules, lettres minuscules
  • (I←⍞)∊: lire les entrées, les stocker I, voir lesquelles sont alphanumériques
  • Z←I⊂⍨: divisé Ien groupes de caractères alphanumériques, stocké dansZ
  • +⌿∘.≡⍨Z: pour chaque élément dans Z, voyez à quelle fréquence il se produit
  • Z,⍪: faire correspondre chaque élément par Zpaire avec le nombre de fois où il se produit
  • G←⊃∪↓: sélectionner uniquement les paires uniques, stocker dans G
  • ⍒,1↓⍉G: obtenir des indices triés pour les occurrences
  • G[... ;]: réorganiser les lignes de Gpar les indices donnés
marinus
la source
6
ce que ... le ... f .....
Ozh
6
C'est pourquoi j'ai des cauchemars.
Thebluefish
3
@Thebluefish: APL a été conçu à partir d'une notation, avec l'intention que tout comme les mathématiques, une notation concise vous libère pour penser clairement. Comme pour les mathématiques, lorsque vous voyez cette notation pour la première fois, vous avez tendance à penser qu'elle n'est pas claire du tout, mais les langues semblent toujours complexes au départ. Il serait plus facile si ce n'était pas sur une seule ligne, mais ...
Phil H
quoi que vous trouviez dans APL, je ne vois que des ordures unicode, des flèches pointant dans les directions et un pin à l'envers. c'est pire que J
bebe
Pourrait être plus court avec ⎕s( help.dyalog.com/latest/Content/Language/System%20Functions/… ) et le nouvel opérateur clé ( help.dyalog.com/latest/Content/Language/Primitive%20Operators/… ):g⌷⍨⊂⍒2⌷⍉g←{⍺,≢⍵}⌸('\w+'⎕s'\0')⍞
ngn
8

C #: 153c 144c 142c 111c 115c 118c 114c 113c

(via LINQPad en mode "Instructions C #", sans inclure la chaîne d'entrée)

Version 1: 142c

var s = "This is a text and a number: 31."; // <- line not included in count
s.Split(s.Where(c=>!Char.IsLetterOrDigit(c)).ToArray(),(StringSplitOptions)1).GroupBy(x=>x,(k,e)=>new{s,c=e.Count()}).OrderBy(x=>-x.c).Dump();

Non golfé:

var s = "This is a text and a number: 31.";
s.Split(                                                     // split string on multiple separators
    s.Where(c => !Char.IsLetterOrDigit(c))                   // get list of non-alphanumeric characters in string
     .ToArray(),                                             // (would love to get rid of this but needed to match the correct Split signature)
    (StringSplitOptions)1                                    // integer equivalent of StringSplitOptions.RemoveEmptyEntries
).GroupBy(x => x, (k, e) => new{ s = k, c = e.Count() })     // count by word
 .OrderBy(x => -x.c)                                         // order ascending by negative count (i.e. OrderByDescending)
 .Dump();                                                    // output to LINQPad results panel

Résultats:

Results

Version 2: 114c

( [\w]comprend _, ce qui est incorrect !; [A-z]inclut [ \ ] ^ _ `; s'installer [^_\W]+)

var s = "This is a text and a number: 31."; // <- line not included in count
Regex.Matches(s, @"[^_\W]+").Cast<Match>().GroupBy(m=>m.Value,(m,e)=>new{m,c=e.Count()}).OrderBy(g=>-g.c).Dump();

Non golfé:

Regex.Matches(s, @"[^_\W]+")                                   // get all matches for one-or-more alphanumeric characters
     .Cast<Match>()                                            // why weren't .NET 1 collections retrofitted with IEnumerable<T>??
     .GroupBy(m => m.Value, (m,e) => new{ m, c = e.Count() })  // count by word
     .OrderBy(g => -g.c)                                       // order ascending by negative count (i.e. OrderByDescending)
     .Dump();                                                  // output to LINQPad results panel

Résultats: (comme version 1)

jimbobmcgee
la source
Soit dit en passant, pour la version 2, votre version non golfée ne correspond pas à votre version golfée. Et puisque vous utilisez une chaîne littérale, vous pouvez écrire@"[^_\W]"
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ - correction de la faute de frappe et suppression du supplément `` pour une économie de 1 caractère - merci !!
jimbobmcgee
7

R, 58 caractères

sort(table(unlist(strsplit(scan(,""),"[[:punct:]]"))),d=T)

Usage:

sort(table(unlist(strsplit(scan(,""),"[[:punct:]]"))),d=T)
1: This is a text and a number: 31.
9: 
Read 8 items

     a     31    and     is number   text   This 
     2      1      1      1      1      1      1 
plannapus
la source
C'est plus court (49 caractères) sort(table(gsub("[[:punct:]]","",scan(,""))),d=T). Malheureusement, les deux solutions ne fonctionnent pas correctement wouldn't.
djhurio
6

perl6: 49 caractères

.say for get.comb(/\w+/).Bag.pairs.sort(-*.value)

Peignez les entrées pour la correspondance des éléments \w+, mettez la liste de mots résultante dans un Bag, demandez leurs paires et triez-les par valeur négative. (C'est *une étoile quelle qu'elle soit , ce n'est pas la multiplication ici)

sortie:

"a" => 2
"This" => 1
"is" => 1
"text" => 1
"and" => 1
"number" => 1
"31" => 1
Ayiko
la source
3
Perl 6 me fait peur.
primo
1
Chaque fois que je pense à une fonctionnalité de langage sympa, je la cherche et elle est quelque part en Perl6. C'est pourquoi ça prend beaucoup de temps ...
Phil H
Vous pouvez couper 6 caractères en utilisant .wordsau lieu de .comb(/\w+/):)
Mouq
@Mouq: malheureusement, .wordsne supprime pas le :ou .de l'entrée comme requis :(
Ayiko
-1. _ne doit pas être inclus dans un mot sous l'énoncé du problème.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
6

Python 101 97

import re
a=re.split('[_\W]+',input())
f=a.count
for w in sorted(set(a),key=f)[::-1]:print w,f(w)

Fonctionne maintenant avec newline:

$ python countword.py <<< '"This is    a text and a number: 31, and a\nnewline"'
a 3
and 2
31 1
number 1
newline 1
is 1
text 1
This 1
daniero
la source
Cela ne fonctionne pas lorsqu'il y a des sauts de ligne ou plusieurs espaces consécutifs dans le texte.
klingt.net
@ klingt.net corrigé.
daniero
6

PHP - 84 octets

<?$a=array_count_values(preg_split('/[_\W]+/',$argv[1],0,1));arsort($a);print_r($a);

L'entrée est acceptée comme argument de ligne de commande, par exemple:

$ php count-words.php "This is a text and a number: 31."

Sortie pour l'exemple de chaîne:

Array
(
    [a] => 2
    [number] => 1
    [31] => 1
    [and] => 1
    [text] => 1
    [is] => 1
    [This] => 1
)
primo
la source
1
il indique que l'entrée est ce que vous voulez. afin que vous puissiez l'obtenir comme paramètre de ligne de commande en utilisant$argv[1]
Einacio
@Einacio bon appel.
primo
-1. Le soulignement _ne doit pas être inclus dans un mot.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ fixe.
primo
5

PowerShell (40)

$s -split"\W+"|group -ca|sort count -des

$ s est une variable qui contient la chaîne d'entrée.

microbien
la source
2
[\W]n'est pas assez bon - il correspond à un espace dans mon test. Et ce n'est pas ordonné par nombre décroissant ...
jimbobmcgee
$s -split"[\W]"|group -ca|where{$_.Name -ne ""}|sort{-$_.Count}vous rapproche (avec des frais, bien sûr)
jimbobmcgee
Oups, j'ai raté la partie de tri. Fixera ma réponse sous peu.
microbian
alternativement:$s -split"\W+"|group -ca |sort count -des
Nacimota
4
-split"\W+"correspond à une chaîne vide entre la dernière .et la fin de la chaîne; \W+correspond également à _ce qui n'est techniquement pas autorisé
jimbobmcgee
4

Perl 69

$h{$_}++for<>=~/\w+/g;print"$_: $h{$_}
"for sort{$h{$b}-$h{$a}}keys%h

Ajout de recommandations de @primo et @protist

Dom Hastings
la source
1
Et le tri?
daniero
@daniero, excellent point! Cela trie maintenant!
Dom Hastings
1
Je pense que c'est à peu près aussi concis que possible. Si cela ne vous dérange pas un avertissement de dépréciation, aucun espace n'est requis entre geet for. L' <=>opérateur peut également être remplacé par -.
primo
2
@primo Ahhh -au lieu de <=>son génie, je ne suis pas sûr que ce soit sur les conseils de golf pour le fil Perl. Je mettrai cela à jour plus tard, merci!
Dom Hastings
1
Hé @protiste, \wcomprend également des chiffres ( perl -e 'print for"a 1 2 3 4 b"=~/\w/g'imprimés a1234b), mais votre mécanisme d'itération des mots enregistre un autre caractère, donc je vais mettre à jour. Merci!
Dom Hastings
4

Powershell: 57 55 53 62 57

(sans inclure la chaîne d'entrée)

$s = "This is a text and a number: 31."    # <-- not counting this line...
[Regex]::Matches($s,"[^_\W]+")|group -ca|sort{-$_.Count}

résultats:

Count Name                      Group
----- ----                      -----
    2 a                         {a, a}
    1 and                       {and}
    1 31                        {31}
    1 number                    {number}
    1 This                      {This}
    1 is                        {is}
    1 text                      {text}

(avec accessoires à @microbian pour le groupe -ca)

jimbobmcgee
la source
3

EcmaScript 6

Version 1 (108 caractères)

s.split(_=/[^a-z\d]/i).map(x=>_[x]=-~_[x]);keys(_).sort((a,b)=>_[a]<_[b]).map(x=>x&&console.log(x+':'+_[x]))

Version 2 (102 caractères)

s.split(_=/[^a-z\d]/i).map(x=>_[x]=-~_[x]);keys(_).sort((a,b)=>_[a]<_[b]).map(x=>x&&alert(x+':'+_[x]))

Version 3 (105 caractères)

s.match(_=/\w+/g).map(x=>_[x]=-~_[x]);alert(keys(_).sort((a,b)=>_[a]<_[b]).map(x=>x+':'+_[x]).join('\n'))

Version 4 (94 caractères)

s.match(_=/\w+/g).map(x=>_[x]=-~_[x]);keys(_).sort((a,b)=>_[a]<_[b]).map(x=>alert(x+':'+_[x]))

Version 5 (sans alerte; 87 caractères)

s.match(_=/\w+/g).map(x=>_[x]=-~_[x]);keys(_).sort((a,b)=>_[a]<_[b]).map(x=>x+':'+_[x])

Version 6 (100 caractères)

keys(_,s.match(_=/\w+/g).map(x=>_[x]=-~_[x])).sort((a,b)=>_[a]<_[b]).map(x=>console.log(x+':'+_[x]))

Sortie:

a:2
31:1
This:1
is:1
text:1
and:1
number:1
Brosse à dents
la source
Vous pouvez changer _[a]et _[b]vers _.aet _.b. Le fait de passer également /\w+/g,_={}à _=/\w+/gproduira le même résultat.
vu le
@eithedog Merci! Cependant, je ne peux pas changer _[a]pour être _.aparce qu'il essaie d'accéder à la propriété "a"de _, pas à la propriété a.
Brosse à dents
ah, correct - la commande ne sera pas conservée. Carry sur :)
eithed
Oh, je n'ai pas remarqué ta réponse .. sympa. Mais .. Object.keysdevient-il mondial dans ES6? Votre réponse semble supposer cela, mais je ne me souviens pas avoir vu cela comme prévu pour ES6.
FireFly
@FireFly Je ne trouve aucune documentation, mais cela fonctionne bien dans Firefox. Je ne l'ai pas testé dans Chrome / Opera / IE.
Brosse à dents
3

Groovy 77 82

changé l'expression régulière de [^\w]+à [^\d\p{L}]+afin de résoudre le problème avec le soulignement

String s = 'This is a text and a number: 31'

def a=s.split(/[^\d\p{L}]+/) 
a.collectEntries{[it, a.count(it)]}.sort{-it.value}

sans première ligne, 82 caractères

sortie:

[a:2, This:1, is:1, text:1, and:1, number:1, 31:1]
Kamil Mikolajczyk
la source
nu_bern'est pas alphanumérique. Cela devrait être 2 mots
Cruncher
Pourquoi utiliser nu_berau lieu de number?
Kevin Fegan
J'ai été induit en erreur par d'autres messages;) maintenant, j'ai supprimé le "_" de l'entrée, mais j'ai corrigé l'expression régulière pour le gérer
Kamil Mikolajczyk
3

GNU awk + coreutils: 71 69

gawk 'BEGIN{RS="\\W+"}{c[$0]++}END{for(w in c)print c[w],w}'|sort -nr

Bien que gawk asortfonctionnant sur des tableaux associatifs, il ne préserve apparemment pas les valeurs d'index, ce qui nécessitesort

printf "This is a text and a number: 31." | 
gawk 'BEGIN{RS="\\W+"}{c[$0]++}END{for(w in c)print c[w],w}'|sort -nr
2 a
1 This
1 text
1 number
1 is
1 and
1 31

GNU awk 4.x: 100 93

Une solution gawk légèrement plus grande mais pure utilisant PROCINFOpour définir l'ordre de tri par défaut pour le tableau associatif (semble nécessiter un gawk relativement récent -> 4.x?)

BEGIN{RS="\\W+";PROCINFO["sorted_in"]="@val_num_desc"}
{c[$0]++}
END{for(w in c)print c[w],w}
tournevis
la source
Oooooh. Je ne connaissais pas PROCINFO. Comme si j'avais besoin d'une autre excuse pour utiliser awk dans ma vie. Vous maudire!
dmckee
@dmckee TBH Je ne connaissais pas PROCINFO jusqu'à ce que je commence à fouiner - j'étais convaincu qu'il devait y avoir un moyen de faire le tri en natif - dommage que les identifiants soient si longs;)
steeldriver
Au mauvais vieux temps, il n'y avait tout simplement pas de moyen. Ce qui mène à des choses comme ma vieille réponse .
dmckee du
-1. Le soulignement _ne doit pas être inclus dans un mot.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
3

Javascript - 132 126 caractères!

(Code JS le plus court)

o={},a=[]
for(i in s=s.split(/[\W_]+/))o[z=s[i]]=o[z]+1||1
for(j in o)a.push([j,o[j]])
a.sort(function(b,c){return c[1]-b[1]})

Amélioration de l'expression régulière et de certaines modifications.


Non golfé

s = s.split(/[\W_]+/), o={}, a=[]; // split along non-char letters, declare object and array

for (i in s) { n = s[i]; o[n] = o[n] + 1 || 1 } // go through each char and store it's occurence

for (j in o) a.push( [j, o[j]] ); // store in array for sorting

a.sort(function (b, c){ return c[1] - b[1]; }); // sort !

<= // make s = "La brillance de ce jour n'est pas"

=> [['est', 3],
['Comment', 1],
['brillant', 1],
['ceci', 1],
['jour', 1],
['isn', 1] ,
['t', 1]]


Old - 156 143 141 140 132 caractères

s=s.split(/[^\w]+/g),o={}
for(i in s){n=s[i];o[n]=o[n]+1||1}a=[]
for(j in o)a.push([j,o[j]])
a.sort(function(b,c){return c[1]-b[1]})

A fait un premier essai au golf. Commentaires appréciés.

Gaurang Tandon
la source
2

EcmaScript 6, 115 100 87 (sans rapide et alerte)

Thanks to @eithedog:

s.match(/\w+/g,a={}).map(w=>a[w]=-~a[w]),keys(a).map(w=>[w,a[w]]).sort((a,b)=>b[1]-a[1])

With prompt and alert (100):

prompt(a={}).match(/\w+/g).map(w=>a[w]=-~a[w]);alert(keys(a).map(w=>[w,a[w]]).sort((a,b)=>b[1]-a[1]))

Run it in Firefox.

teh_senaus
la source
1
You don't need var . Also, you can move a={} inside prompt - prompt(a={}). You can also drop Object. and change w=>a[w]=a[w]+1||1 to w=>a[w]=-~a[w]
eithed
Very nice. Beats the working Python one now :)
teh_senaus
Same as for @toothbrush's answer - moving the declaration of a from prompt to regexp will spare two more chars.
eithed
It's nice and clean. Good job!
Toothbrush
-1. Underscore _ should not be included in a word.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
2

Ruby 58 82 65

h=Hash.new 0
gets.scan(/[\d\w]+/){h[$&]+=1}
p *h.sort_by{|k,v|-v}

Test run:

$ ruby counttext.rb <<< "This is a text and a number: 31."
["a", 2]
["text", 1]
["This", 1]
["is", 1]
["and", 1]
["number", 1]
["31", 1]

Edit 58->80: Ok, I was way off. I forgot to sort the words by occurrences. Also, Array#uniq is not an enumerator, but uses a given block to compare elements, so passing puts to it didn't filter out duplicates (not that it says that we should).

daniero
la source
1
Maybe split(/\W+/) instead of scan (untested)?
Howard
@Howard Thanks. \W excludes _ so that had to be fixed, but it still saved 2 characters (then I added 20 to fix the sorting that I had neglected).
daniero
Shouldn't be sorted in reverse (a=gets.split(/[_\W]+/)).uniq.map{|w|[w,a.count(w)]}.sort_by(&:last).reverse.map{|x|p x}
Eduard Florinescu
@EduardFlorinescu Nah. reverse is way too verbose ;) Btw, it's not fair changing the question.
daniero
If you see in the output sample it was sorted descended only that I forgot to specify it.
Eduard Florinescu
2

F# - 169

let f s=(s+"").Split(set s-set(['a'..'z']@['A'..'Z']@['0'..'9'])|>Set.toArray)|>Seq.where((<>)"")|>Seq.countBy id|>Seq.sortBy((~-)<<snd)|>Seq.iter((<||)(printfn"%s:%d"))

Degolfed:

let count (s : string) =
    s.Split (set s - set (['a'..'z']@['A'..'Z']@['0'..'9']) |> Set.toArray)
 |> Seq.where ((<>) "")
 |> Seq.countBy id
 |> Seq.sortBy ((~-) << snd)
 |> Seq.iter ((<||) (printfn "%s:%d"))

Output when called from fsi:

> "This is a text and a number: 31." |> f
a:2
This:1
is:1
text:1
and:1
number:1
31:1
val it : unit = ()

Update: Some explanation as requested in the comments.

Uses set functions to generate an array of non alphanumeric characters in the input to pass to String.Split, then uses sequence functions to filter out empty strings, generate word counts and print the result.

Some golfing tricks: Adds an empty string to the function argument s to force type inference of the argument as a string rather than explicitly declaring the type. Uses Seq.where rather than Seq.filter to save a few characters (they are synonyms). Mixes forward pipe and ordinary function application in an attempt to minimize characters. Uses currying and (op) syntax to treat <> ~- and <|| operators as regular functions to avoid declaring lambdas to filter empty strings, sort by descending count and print tuples.

mattnewport
la source
You should definitely insert some sort of explanation; that way we can understand your code.
Justin
Added a degolfed version and some explanation.
mattnewport
2

Python - 95 ( now 87 thanks to @primo)

d=__import__('re').findall(r'\w+',raw_input())
print sorted(map(lambda y:(y,d.count(y)),d))

Sample input :

'This is a text and a number: 31'

Sample output :

[('This', 1),('is', 1), ('a', 2),('text', 1),('and', 1),('a', 2),('number', 1),('31', 1)]

Any improvement sugestion would be appreciated

Azwr
la source
1
The solution is nice but the output is not sorted.
Eduard Florinescu
What do you mean by sorted? Thanks for the comment.
Azwr
1
\w matches [a-zA-Z0-9_]. Your entire regex can be replaced by r'\w+'. Also, the x variable is not needed, just use raw_input() as the second parameter to findall.
primo
By sorted, the OP means that the words that appear most often need to be listed first. Also, your program should include a print statement (i.e. print map(...), otherwise it's not a complete program.
primo
I don't have time to sort it right now :( I'm in a hurry , thanks for the suggestions and comments.
Azwr
2

JavaScript 160 144 (Edited: to meet requirements)

f=Function;o={};s.replace(/\w+/g,f('a','o[a]=++o[a]||1'));Object.keys(o).sort(f('b,c','return o[c]-o[b]')).map(f('k','console.log(k+" "+o[k])'))

Unminified:

f=Function;
o = {};
s.replace(/\w+/g, f('a','o[a]=++o[a]||1'));
Object.keys(o).sort(f('b,c', 'return o[c]-o[b]')).map(f('k','console.log(k+" "+o[k])'))

Logs each word to console in order, passing the following string:

s="This is sam}}ple text 31to test the effectiveness of this code, you can clearly see that this is working-as-intended, but you didn't doubt it did you?.";

Outputs:

you 3
this 2
is 2
can 1
text 1
31to 1
test 1
the 1
effectiveness 1
of 1
This 1
code 1
sam 1
ple 1
clearly 1
see 1
that 1
working 1
as 1
intended 1
but 1
didn 1
t 1
doubt 1
it 1
did 1 

I don't have the heart to use alert().

George Reith
la source
1
The sort should be by the number. of occurrences so you should be first.
Eduard Florinescu
@EduardFlorinescu Silly me... I'll fix it later.
George Reith
@EduardFlorinescu fixed
George Reith
-1. Underscore _ should not be included in a word.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
++o[a]||1 => -~o[a]
l4m2
2

k [71 chars]

f:{s:" ",x;`_k!m@k:|(!m)@<.:m:#:'=`$1_'(&~((),/:s)like"[a-zA-Z0-9]")_s}

Any other character except alphanumeric chars will be considered as delimiter.

example

f "This is a text and a number: 31."
a     | 2
31    | 1
number| 1
and   | 1
text  | 1
is    | 1
This  | 1

example

f "won't won won-won"
won| 4
t  | 1
nyi
la source
2

Javascript (135)

u=/\w+/g
for(i=s.length;i--;)for(w in a=s.match(u))u[w=a[w]]=u[w]||a.reduce(function(p,c){return p+=w==c},0)==i&&!console.log(w+":"+i)

Unminified:

u=/\w+/g;for (i=s.length;i--;)
    for(w in a=s.match(u))
        u[w=a[w]] = u[w] || 
           a.reduce(function(p,c){return p+=w==c},0)==i && !console.log(w+":"+i)

Loops over every possible number of matches in descending order, and outputs words with that number of occurrences. Just to be horrible.

Notes: Alert would have reduced the length some. Strictly speaking alphanumeric should be [^\W_]

Zachary Vance
la source
2

Haskell (153 = 104 code + 49 import)

Pretty straight-forward, totally composed function... no argument even necessary! This is my first golf, so go easy, maybe? :)

import Data.Char
import Data.List
import Data.Ord
so=reverse.(sortBy$comparing snd).(map(\t@(x:_)->(x,length t))).group.sort.(map$filter isAlphaNum).words

Output:

*Main> so "This is a text and a number: 31."
[("a",2),("text",1),("number",1),("is",1),("and",1),("This",1),("31",1)]
Alex Reinking
la source
2

q (50)

desc count each group" "vs ssr[;"[^0-9A-Za-z]";" "]
  • ssr replaces non alphanumeric
  • " "vs splits the result into a symbol list
  • count each group counts creates a dict matching distinct elements of the list with the number of occurances
  • desc sorts the dict by descending values

edit: fixed accidentally matching ascii 58-64 and 91-96

nightTrevors
la source
1
I've no knowledge of q but is the regex [0-z] ASCII-based? If it is, wouldn't it also include ASCII chars 58-64? Because those are : ; < = > ? @.
jimbobmcgee
Great catch jimbob, thanks
nightTrevors
You're welcome; only spotted because I found the same in C#. Sadly, same with [A-z], which matches ASCII 91-96, which are `[ \ ] ^ _ ``
jimbobmcgee
ah right you are, nice little ascii lesson right there!
nightTrevors
I just discovered [^_\W]+ for mine, which should be "exclude non-word characters and underscore", if your syntax supports the \W class...
jimbobmcgee
2

Pure Bash (no external programs), 164

This is longer than I'd hoped, but I wanted to see if the necessary counting and sorting (in the right direction) could be done purely with bash arrays (associative and non-associative):

declare -A c
for w in ${@//[[:punct:]]/ };{ ((c[$w]++));}
for w in ${!c[@]};{ i=${c[$w]};((m=i>m?i:m));s[$i]+=$w:;}
for((i=m;i>0;i--));{ printf "${s[i]//:/:$i
}";}

Save as a script file, chmod +x, and run:

$ ./countoccur This is a text and a number: 31.
a:2
and:1
number:1
text:1
31:1
is:1
This:1
$ 
Digital Trauma
la source
2

AWK

awk -vRS='[^A-Za-z0-9]' '$0{c[$0]++}END{for(i in c)print c[i]"\t"i": "c[i]|"sort -nr|cut -f2-"}'

Does the job without gawkish extensions:

$ echo 'This is a text and a number: 31.' | awk -vRS='[^A-Za-z0-9]' '$0{c[$0]++}END{for(i in c)print c[i]"\t"i": "c[i]|"sort -nr|cut -f2-"}'
a: 2
This: 1
text: 1
number: 1
is: 1
and: 1
31: 1

If printing "count: word" instead, it would be a bit shorter but I wanted to mimic the given example output...


la source
2

Tcl, 99 bytes

proc C s {lmap w [split [regsub -all \[^\\w|\ \] $s {}]] {dict inc D $w}
lsort -s 2 -inde 1 -de $D}

Try it online!

sergiol
la source
1

Python 2.X (108 - Characters)

print'\n'.join('{}:{}'.format(a,b)for a,b in __import__("collections").Counter(raw_input().split()).items())

Python 3.X (106 - Characters)

print('\n'.join('{}:{}'.format(a,b)for a,b in __import__("collections").Counter(input().split()).items())
Abhijit
la source
Separators will be anything that is not alpha-numeric - You only split on whitespace.
daniero
1

Haskell - 137

import Data.List
count text=let textS=(words(text\\".-\':")) in (sortBy (\(_,n) (_,m) -> compare m n)).nub$map(\t->(t,(length.(filter(==t)))textS)) textS
Landarzar
la source
Doesn't fulfill the condition that non-alphanumeric should be separator.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
1

Python 3 - 76

The requirement of splitting on non-alphanumeric chars unfortunately extends the code by 19 chars. The output of the following is shown correctly. If you are not sure, add a .most_common() after the .Counter(...).

i=__import__
print(i('collections').Counter(i('re').findall('\w+',input())))

In/Output

Given the input of This is a text and a number: 31. you get following output:

Counter({'a': 2, 'is': 1, 'This': 1, 'and': 1, '31': 1, 'number': 1, 'text': 1})

I tried it with other values like

1 2 3 4 5 6 7 8 2 1 5 3 4 6 8 1 3 2 4 6 1 2 8 4 3 1 3 2 5 6 5 4  2 2 4 2 1 3 6

to ensure, the output-order does not rely on the key's value/hash. This example produces:

Counter({'2': 8, '3': 6, '1': 6, '4': 6, '6': 5, '5': 4, '8': 3, '7': 1})

But as I said, print(i('collections').Counter(i('re').findall('\w+',input())).most_common()) would return the results as an definitly ordered list of tuples.


Python 3 - 57 (if a space would be enough for splitting :P)

print(__import__('collections').Counter(input().split()))
Dave J
la source
If you assumed the string was in some variable s, as some other answers do, you could lose 6 characters by replacing input().
Phil H
@PhilH well. you are right, but I would never read that out of the requirements. sure the "string for JavaScript"-part might suggest it, but I cannot, with a clear conscience, interpret a string-variable as a valid "input". But you are right. that would shorten it even more. :P
Dave J
-1. Underscore _ should not be included in a word.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
Well this depends on the definition of alpha-numeric. In Python, "\w" is defined for accepting alpha-numeric chars. You might be correct but a with this kind of interpretation of the rules, my solution keeps being correct. :)
Dave J