Cuenta las palabras en un texto y muéstralas

26

El código debe ingresar un texto (no obligatorio puede ser cualquier archivo, stdin, cadena para JavaScript, etc.):

This is a text and a number: 31.

La salida debe contener las palabras con su número de ocurrencias, ordenadas por el número de ocurrencias en orden descendente:

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

Tenga en cuenta que 31 es una palabra, por lo que una palabra es cualquier cosa alfanumérica, el número no actúa como separador, por ejemplo, 0xAFcalifica como una palabra. Los separadores serán cualquier cosa que no sea alfanumérica, incluidos .(punto) y -(guión), i.e.o pick-me-upque resulten en 2 respectivamente 3 palabras. Debería distinguir entre mayúsculas Thisy minúsculas, y thisserían dos palabras diferentes, 'también sería un separador wouldny tserían 2 palabras diferentes de wouldn't.

Escriba el código más corto en su idioma de elección.

La respuesta correcta más corta hasta ahora:

Eduard Florinescu
fuente
55
¿Importa el caso (es decir, es Thisigual que thisy tHIs)?
Gareth
Si algo no alfanumérico cuenta como separador, ¿son wouldn't2 palabras ( wouldny t)?
Gareth
@Gareth debería ser sensible a mayúsculas y minúsculas, Thisy de thishecho serían dos palabras diferentes, iguales wouldny t.
Eduard Florinescu
Si no serían 2 palabras, ¿no deberían ser "would" y "nt", ya que es la abreviatura de "wouldn't", o es demasiado gramatical nazi-ish?
Teun Pronk
@TeunPronk Intento que sea simple, poner algunas reglas alentará las excepciones para que estén en orden con la gramática, y hay muchas excepciones por ahí. Ex en inglés i.e.es una palabra, pero si dejamos el punto todos los puntos en el Se tomará el final de las frases, lo mismo con comillas o comillas simples, etc.
Eduard Florinescu

Respuestas:

27

grep y coreutils  44  42

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

Prueba:

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

Resultados en:

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

Actualizar

  • Use la opción que no distingue entre mayúsculas y minúsculas y expresiones regulares más cortas. Gracias tomas.
Thor
fuente
2
Esta es casi exactamente la respuesta de McEllroy al libro de Knuth, Literate Programming . La única diferencia es que esto no incluye una tubería al headfinal.
AJMansfield
Esto fue más o menos mi primer pensamiento también.
Rob
1
¿No funcionaría '\ w +' también?
Sylwester
1
41 personajes :grep -io \[A-Z0-9]*|sort|uniq -c|sort -nr
Tomás
1
@Tomas: Agregó esto a la respuesta, gracias. Dejé la protección para el asterisco, porque estaba expandiendo los nombres de los archivos en algunos shells.
Thor
18

Java 8: 289

Lo cual es bastante bueno, ya que Java es un lenguaje muy ajeno al golf.

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()));}

Sin 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()));
    }
}

Ejecutar desde la línea de comando:

java -jar wordCounter.jar This is a text and a number: 31.
AJMansfield
fuente
Regex incorrecto para dividir. Debería ser"[^\\W_]"
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳, el String.split(String regex)método toma un patrón que coincide con el delimitador para dividirlo. Entonces, por ejemplo, "aababba".split("b")produciría la matriz {"aa", "a", "", "a"}. Mi expresión regular [^\\w\\d]significa 'un carácter en la palabra carácter ni en las clases de caracteres de dígitos'. [^\\W_]es, en cambio, "un carácter que no es un guión bajo ni está en la clase de caracteres que no son palabras" y coincidiría con cualquier carácter de palabra excepto el guión bajo.
AJMansfield
Lo siento, mi comentario anterior fue incorrecto. \wincluye \d, por lo que \des redundante. \wincluye guión bajo, que debe considerarse un separador de acuerdo con la pregunta. Entonces, la expresión regular correcta para la división debe ser "[\\W_]+".
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ ok, gracias; He solucionado el problema.
AJMansfield
17

APL (57)

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

p.ej

      ⎕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

Explicación:

  • ⎕D,⎕A,⎕UCS 96+⍳26: números, letras mayúsculas, letras minúsculas
  • (I←⍞)∊: leer entrada, almacenar I, ver cuáles son alfanuméricos
  • Z←I⊂⍨: dividido Ien grupos de caracteres alfanuméricos, almacenar enZ
  • +⌿∘.≡⍨Z: para cada elemento en Z, vea con qué frecuencia ocurre
  • Z,⍪: empareja cada elemento en Zpares con la cantidad de veces que ocurre
  • G←⊃∪↓: seleccione solo los pares únicos, almacene en G
  • ⍒,1↓⍉G: obtener índices ordenados para las ocurrencias
  • G[... ;]: reordenar las líneas de Gpor los índices dados
marinus
fuente
66
qué ... la ... f .....
Ozh
66
Por eso tengo pesadillas.
Thebluefish
3
@Thebluefish: APL fue diseñado a partir de una notación, con la intención de que, al igual que las matemáticas, una notación concisa te libere para pensar con claridad. Nuevamente, como las matemáticas, cuando ves esa notación por primera vez, tiendes a pensar que no está nada clara, pero los idiomas siempre parecen complejos para empezar. Sin embargo, sería más fácil si no estuviera todo en una línea ...
Phil H
lo que sea que se te ocurra en APL solo veo un poco de basura unicode, flechas apuntando en direcciones y un pino al revés. eso es peor que J
bebe
Podría ser más corto con ⎕s( help.dyalog.com/latest/Content/Language/System%20Functions/… ) y el nuevo operador clave ( 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

(a través de LINQPad en modo "C # Statements", sin incluir la cadena de entrada)

Versión 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();

Sin 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

Resultados:

Resultados

Versión 2: 114c

( [\w]incluye _, que es incorrecto; [A-z]incluye [ \ ] ^ _ `; establecerse [^_\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();

Sin 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

Resultados: (como la Versión 1)

jimbobmcgee
fuente
Por cierto, para la versión 2, su versión sin golf no coincide con su versión de golf. Y como está usando una cadena literal, puede escribir@"[^_\W]"
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ el
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ - reparó el error tipográfico y eliminó el extra `` para ahorrar 1-char - ¡gracias!
jimbobmcgee
7

R, 58 char

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

Uso:

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
fuente
Esto es más corto (49 caracteres) sort(table(gsub("[[:punct:]]","",scan(,""))),d=T). Lamentablemente, ambas soluciones no funcionan correctamente wouldn't.
djhurio 01 de
6

perl6: 49 caracteres

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

Peine la entrada para la coincidencia de cosas \w+, coloque la lista resultante de palabras en a Bag, solicite sus pares y ordénelos por valor negativo. (El *es una estrella Lo que sea , no es multiplicación aquí)

salida:

"a" => 2
"This" => 1
"is" => 1
"text" => 1
"and" => 1
"number" => 1
"31" => 1
Ayiko
fuente
3
Perl 6 me da miedo.
primo
1
Cada vez que pienso en una característica de lenguaje genial, la busco y está en Perl6 en alguna parte. Por eso lleva tanto tiempo ...
Phil H
Puede recortar 6 caracteres usando en .wordslugar de .comb(/\w+/):)
Mouq
@Mouq: desafortunadamente .wordsno elimina el :o .de la entrada como se requiere :(
Ayiko
-1. _no debe incluirse en una palabra debajo del enunciado del problema.
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)

Ahora funciona con nueva línea:

$ 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
fuente
Esto no funciona cuando hay líneas nuevas o más de un espacio consecutivo en el texto.
klingt.net
@ klingt.net corregido.
daniero
6

PHP - 84 bytes

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

La entrada se acepta como un argumento de línea de comando, por ejemplo:

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

Salida para la cadena de muestra:

Array
(
    [a] => 2
    [number] => 1
    [31] => 1
    [and] => 1
    [text] => 1
    [is] => 1
    [This] => 1
)
primo
fuente
1
dice que la entrada es lo que quieres. para que pueda obtenerlo como parámetro de línea de comando usando$argv[1]
Einacio
@Einacio buena llamada.
primo
-1. El guión bajo _no debe incluirse en una palabra.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ arreglado.
primo
5

PowerShell (40)

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

$ s es una variable que contiene la cadena de entrada.

microbiano
fuente
2
[\W]no es lo suficientemente bueno, coincide con un espacio en mi prueba. Y no está ordenado por conteo descendente ...
jimbobmcgee
$s -split"[\W]"|group -ca|where{$_.Name -ne ""}|sort{-$_.Count}te acerca (con los costos, por supuesto)
jimbobmcgee
Vaya, me perdí la parte de clasificación. Arreglará mi respuesta en breve.
microbio
alternativamente:$s -split"\W+"|group -ca |sort count -des
Nacimota
44
-split"\W+"está haciendo coincidir una cadena vacía entre el último .y el final de la cadena; también \W+coincide con lo _que técnicamente no está permitido
jimbobmcgee
4

Perl 69

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

Se agregaron recomendaciones de @primo y @protist

Dom Hastings
fuente
1
¿Qué pasa con la clasificación?
daniero
@daniero, excelente punto! ¡Esto ahora ordena!
Dom Hastings
1
Creo que es lo más breve posible. Si no le importa una advertencia de desaprobación, no se requiere espacio entre gey for. Además, el <=>operador puede ser reemplazado por -.
primo
2
@primo Ahhh en -lugar de <=>es genial, no estoy seguro de que esté en los consejos de golf para el hilo de Perl. Actualizaré esto más tarde, ¡gracias!
Dom Hastings
1
Hola @protist, también \wincluye números ( perl -e 'print for"a 1 2 3 4 b"=~/\w/g'impresiones a1234b), pero tu mecanismo para iterar las palabras guarda otro carácter, así que lo actualizaré. ¡Gracias!
Dom Hastings
4

Powershell: 57 55 53 62 57

(sin incluir la cadena de entrada)

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

devoluciones:

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}

(con accesorios para @microbian para el grupo -ca)

jimbobmcgee
fuente
3

EcmaScript 6

Versión 1 (108 caracteres)

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

Versión 2 (102 caracteres)

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

Versión 3 (105 caracteres)

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

Versión 4 (94 caracteres)

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

Versión 5 (sin alerta; 87 caracteres)

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

Versión 6 (100 caracteres)

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

Salida:

a:2
31:1
This:1
is:1
text:1
and:1
number:1
Cepillo de dientes
fuente
Puedes cambiar _[a]y _[b]a _.ay _.b. También cambiar /\w+/g,_={}a _=/\w+/gproducirá el mismo resultado.
Publicado el
@eithedog Gracias! Sin embargo, no puedo cambiar _[a]para ser _.aporque intenta acceder a la propiedad "a"de _, no a la propiedad a.
Cepillo de dientes
ah, correcto, el orden no se mantendrá. Continuar :)
eithed
Oh, no noté tu respuesta ... agradable. Pero ... ¿se está Object.keysconvirtiendo en un global en ES6? Su respuesta parece asumir esto, pero no recuerdo haberlo visto como estaba programado para ES6.
FireFly
@FireFly No puedo encontrar ninguna documentación, pero funciona bien en Firefox. No lo he probado en Chrome / Opera / IE.
Cepillo de dientes
3

Maravilloso 77 82

Se modificó la expresión regular de [^\w]+a [^\d\p{L}]+para resolver el problema con el guión bajo

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}

sin primera línea, 82 caracteres

salida:

[a:2, This:1, is:1, text:1, and:1, number:1, 31:1]
Kamil Mikolajczyk
fuente
nu_berno es alfanumérico Esto debería ser 2 palabras
Cruncher
¿Por qué usar en nu_berlugar de number?
Kevin Fegan
Fui engañado por otras publicaciones;) ahora eliminé el "_" de la entrada, pero arreglé la expresión regular para manejarlo
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

Aunque gawk asortfunciona en matrices asociativas, aparentemente no conserva los valores de índice, por lo que necesita el externosort

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

Una solución gawk ligeramente más grande pero pura que se usa PROCINFOpara establecer el orden de clasificación predeterminado para la matriz asociativa (parece requerir un gawk relativamente reciente -> 4.x?)

BEGIN{RS="\\W+";PROCINFO["sorted_in"]="@val_num_desc"}
{c[$0]++}
END{for(w in c)print c[w],w}
conductor de acero
fuente
Oooooh No sabía sobre PROCINFO. Como si necesitara otra excusa para usar awk en mi vida. ¡Te maldigo!
dmckee 01 de
@dmckee TBH yo no sabía nada de Procinfo hasta que empecé a hurgar - Yo estaba convencido de que tenía que haber una manera de hacer el tipo de forma nativa - es una pena los identificadores son tan largas;)
steeldriver
En los viejos tiempos simplemente no había manera. Lo que lleva a cosas como esta vieja respuesta mía .
dmckee
-1. El guión bajo _no debe incluirse en una palabra.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
3

Javascript - 132 126 caracteres!

(Código JS más corto)

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

Se mejoró la expresión regular y algunas ediciones.


Sin 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 = "Lo brillante que es este día no lo es"

=> [['' es ', 3],
[' Cómo ', 1],
[' brillante ', 1],
[' esto ', 1],
[' día ', 1],
[' isn ', 1] ,
['t', 1]]


Viejo - 156 143 141 140 132 caracteres

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

Dio un primer intento en el golf. Comentarios apreciados.

Gaurang Tandon
fuente
2

EcmaScript 6, 115 100 87 (sin aviso y alerta)

Gracias a @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])

Con aviso y alerta (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]))

Ejecútalo en Firefox.

teh_senaus
fuente
1
No es necesario var . Además, puedes moverte a={}dentro prompt- prompt(a={}). También puede soltar Object.y cambiar w=>a[w]=a[w]+1||1aw=>a[w]=-~a[w]
eithed
Muy agradable. Beats the Python one de trabajo ahora :)
teh_senaus
Lo mismo que para la respuesta de @ toothbrush: mover la declaración de aprompt a regexp ahorrará dos caracteres más.
Eithed
Es bonito y limpio. ¡Buen trabajo!
Cepillo de dientes
-1. El guión bajo _no debe incluirse en una palabra.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
2

Rubí 58 82 65

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

Prueba de funcionamiento:

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

Editar 58-> 80: Ok, estaba muy lejos. Olvidé ordenar las palabras por ocurrencias. Además, Array#uniqno es un enumerador, pero usa un bloque dado para comparar elementos, por lo que pasarlo putsno filtró duplicados (no es que diga que deberíamos).

daniero
fuente
1
Tal split(/\W+/)vez en lugar de scan(no probado)?
Howard
@Howard Gracias. \Wexcluye, por _lo que tuvo que repararse, pero aún así guardó 2 caracteres (luego agregué 20 para corregir la clasificación que había descuidado).
daniero
No debería clasificarsereverse (a=gets.split(/[_\W]+/)).uniq.map{|w|[w,a.count(w)]}.sort_by(&:last).reverse.map{|x|p x}
Eduard Florinescu
@EduardFlorinescu Nah. reversees demasiado detallado;) Por cierto, no es justo cambiar la pregunta.
daniero
Si ve en la muestra de salida, se ordenó descendió solo que olvidé especificarlo.
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"))

Salida cuando se llama desde 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 = ()

Actualización: alguna explicación según lo solicitado en los comentarios.

Utiliza funciones de conjunto para generar una matriz de caracteres no alfanuméricos en la entrada para pasar a String.Split, luego usa funciones de secuencia para filtrar cadenas vacías, generar recuentos de palabras e imprimir el resultado.

Algunos trucos de golf: agrega una cadena vacía al argumento de función s para forzar la inferencia de tipo del argumento como una cadena en lugar de declarar explícitamente el tipo. Utiliza Seq.where en lugar de Seq.filter para guardar algunos caracteres (son sinónimos). Mezcla la aplicación de canalización hacia adelante y la función ordinaria en un intento de minimizar los caracteres. Utiliza curry y (op) sintaxis para tratar <> ~ - y <|| operadores como funciones regulares para evitar declarar lambdas para filtrar cadenas vacías, ordenar por conteo descendente e imprimir tuplas.

Mattnewport
fuente
Definitivamente deberías insertar algún tipo de explicación; De esa manera podemos entender su código.
Justin
Se agregó una versión desadaptada y alguna explicación.
mattnewport
2

Python - 95 (ahora 87 gracias a @primo)

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

Entrada de muestra:

'This is a text and a number: 31'

Salida de muestra:

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

Cualquier mejora en la sugestión sería apreciada

Azwr
fuente
1
La solución es buena pero la salida no está ordenada.
Eduard Florinescu
¿Qué quieres decir con ordenado? Gracias por el comentario.
Azwr
1
\wpartidos [a-zA-Z0-9_]. Toda su expresión regular puede ser reemplazada por r'\w+'. Además, la xvariable no es necesaria, solo se usa raw_input()como segundo parámetro parafindall .
primo
Ordenado, el OP significa que las palabras que aparecen con mayor frecuencia deben enumerarse primero. Además, su programa debe incluir una printdeclaración (es decir,print map(... ), de lo contrario no es un programa completo.
primo
No tengo tiempo para ordenarlo ahora :( Tengo prisa, gracias por las sugerencias y comentarios.
Azwr
2

JavaScript 160 144 (Editado: para cumplir con los requisitos)

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

No minificado:

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

Registra cada palabra en la consola en orden, pasando la siguiente cadena:

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?.";

Salidas:

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 

No tengo el corazón para usar alert().

George Reith
fuente
1
El orden debe ser por número. de ocurrencias por lo que youdebe ser el primero.
Eduard Florinescu
@EduardFlorinescu, tonto ... Lo arreglaré más tarde.
George Reith
@EduardFlorinescu arreglado
George Reith
-1. El guión bajo _no debe incluirse en una palabra.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
++o[a]||1=>-~o[a]
l4m2
2

k [71 caracteres]

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

Cualquier otro carácter, excepto los caracteres alfanuméricos, se considerará como delimitador.

ejemplo

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

ejemplo

f "won't won won-won"
won| 4
t  | 1
nyi
fuente
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)

No minificado:

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)

Recorre cada número posible de coincidencias en orden descendente y genera palabras con ese número de ocurrencias. Solo para ser horrible.

Notas: La alerta habría reducido algo la longitud. Estrictamente hablando, alfanumérico debería ser[^\W_]

Zachary Vance
fuente
2

Haskell (153 = 104 código + 49 importación)

Función bastante sencilla y totalmente compuesta ... ¡ni siquiera es necesario un argumento! Este es mi primer golf, así que, ¿qué tal? :)

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

Salida:

*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
fuente
2

q (50)

desc count each group" "vs ssr[;"[^0-9A-Za-z]";" "]
  • ssr reemplaza no alfanumérico
  • "" vs divide el resultado en una lista de símbolos
  • contar cada grupo cuenta crea un dict que combina elementos distintos de la lista con el número de ocurrencias
  • desc ordena el dict por valores descendentes

editar: arreglado accidentalmente ascii 58-64 y 91-96

sabores nocturnos
fuente
1
No tengo conocimiento, qpero ¿se [0-z]basa la expresión regular ASCII? Si es así, ¿no incluiría también los caracteres ASCII 58-64? Porque esos son : ; < = > ? @.
jimbobmcgee
Gran captura jimbob, gracias
nightTrevors 03 de
De nada; solo visto porque encontré lo mismo en C #. Lamentablemente, lo mismo con [A-z], que coincide con ASCII 91-96, que son `[\] ^ _` `
_`
Ah, claro que sí, una pequeña lección de ascii allí mismo.
nightTrevors
Acabo de descubrir [^_\W]+ por la mía, que debe ser "excluir caracteres que no son de texto y subrayado" , si su sintaxis es compatible con la \Wclase ...
jimbobmcgee
2

Pure Bash (sin programas externos), 164

Esto es más largo de lo que esperaba, pero quería ver si el recuento y la ordenación necesarios (en la dirección correcta) se podían hacer exclusivamente con bashmatrices (asociativas y no asociativas):

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
}";}

Guardar como un archivo de script chmod +x, y ejecutar:

$ ./countoccur Este es un texto y un número: 31.
a: 2
y 1
numero 1
Texto 1
31: 1
es: 1
Esto: 1
PS 
Trauma digital
fuente
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-"}'

¿El trabajo sin extensiones gawkish:

$ 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

Si imprime "count: word" en su lugar, sería un poco más corto, pero quería imitar el resultado del ejemplo dado ...


fuente
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}

Pruébalo en línea!

sergiol
fuente
1

Python 2.X (108 - Personajes)

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

Python 3.X (106 - Personajes)

print('\n'.join('{}:{}'.format(a,b)for a,b in __import__("collections").Counter(input().split()).items())
Abhijit
fuente
Separators will be anything that is not alpha-numeric- Solo se divide en espacios en blanco.
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
fuente
No cumple la condición de que los caracteres no alfanuméricos sean separadores.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
1

Python 3 - 76

Desafortunadamente, el requisito de división en caracteres no alfanuméricos extiende el código en 19 caracteres. El resultado de lo siguiente se muestra correctamente. Si no está seguro, agregue un .most_common()después de .Counter(...).

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

Entrada / salida

Dada la entrada de This is a text and a number: 31.usted obtiene la siguiente salida:

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

Lo probé con otros valores como

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

para garantizar, el orden de salida no depende del valor / hash de la clave. Este ejemplo produce:

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

Pero como dije, print(i('collections').Counter(i('re').findall('\w+',input())).most_common())devolvería los resultados como una lista definitivamente ordenada de tuplas.


Python 3 - 57 (si un espacio fuera suficiente para dividir: P)

print(__import__('collections').Counter(input().split()))
Dave J
fuente
Si asumió que la cadena estaba en alguna variable s, como lo hacen algunas otras respuestas, podría perder 6 caracteres al reemplazar input ().
Phil H
@PhilH bien. tienes razón, pero nunca leería eso fuera de los requisitos. Seguro que la parte "cadena para JavaScript" podría sugerirlo, pero no puedo, con la conciencia tranquila, interpretar una variable de cadena como una "entrada" válida. Pero tienes razón. eso lo acortaría aún más. : P
Dave J
-1. El guión bajo _no debe incluirse en una palabra.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
Bueno, esto depende de la definición de alfanumérico. En Python, "\ w" se define para aceptar caracteres alfanuméricos. Puede que tengas razón, pero con este tipo de interpretación de las reglas, mi solución sigue siendo correcta. :)
Dave J