Conte as palavras em um texto e exiba-as


26

O código deve receber um texto de entrada (não obrigatório, pode ser qualquer arquivo, stdin, string para JavaScript, etc):

This is a text and a number: 31.

A saída deve conter as palavras com seu número de ocorrência, classificadas pelo número de ocorrências em ordem decrescente:

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

Observe que 31 é uma palavra; portanto, uma palavra é qualquer coisa alfanumérica; o número não está atuando como separador; portanto, por exemplo, é 0xAFqualificado como uma palavra. Separadores serão qualquer coisa que não seja alfanumérica, incluindo .(ponto) e -(hífen), portanto, i.e.ou pick-me-upresultariam em 2, respectivamente, 3 palavras. Deve ser sensível a maiúsculas e minúsculas Thise thisincluir duas palavras diferentes, 'também seria um separador wouldne tserão 2 palavras diferentes dewouldn't .

Escreva o código mais curto no seu idioma de escolha.

Resposta correta mais curta até agora:


5
O caso importa (isto é, é Thiso mesmo que thise tHIs)?
Gareth

Se algo não alfanumérico conta como separador, são wouldn't2 palavras ( wouldne t)?
Gareth

@Gareth Deve fazer distinção entre maiúsculas e minúsculas Thise thisseria de fato duas palavras diferentes, iguais wouldne t.
Eduard Florinescu

Se não seriam duas palavras, não deveria ser "seria" e "nt", já que é a abreviação de não seria, ou isso é muito mais nazista?
Teun Pronk

@TeunPronk Eu tento simplificar, colocar algumas regras incentivará as exceções a estarem em ordem com a gramática, e há muitas exceções por aí. Ex em inglês i.e.é uma palavra, mas se deixarmos todos os pontos no ponto final de frases serão tomadas, mesmo com aspas ou plicas, etc.
Eduard Florinescu

Respostas:


27

grep e coreutils  44  42

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

Teste:

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

Resulta em:

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

Atualizar

  • Use a opção que não diferencia maiúsculas de minúsculas e regex mais curto. Obrigado Tomas.

2
Sendo essa quase exatamente a resposta de McEllroy ao livro de Knuth, Literate Programming . A única diferença é que isso não inclui um tubo headno final.
AJMansfield

Este foi praticamente o meu primeiro pensamento também.
Rob

1
'\ W +' também não funcionaria?
precisa

1
41 caracteres :grep -io \[A-Z0-9]*|sort|uniq -c|sort -nr
Tomas

1
Tomas @: Adicionado isso à resposta, obrigado. Eu saí em proteção para o asterisco, porque ele estava expandindo nomes de arquivos em algumas conchas.
Thor

18

Java 8: 289

O que é muito bom, pois o java é uma linguagem muito não-golfe.

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

Ungolfed:

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

Execute a partir da linha de comando:

java -jar wordCounter.jar This is a text and a number: 31.

Regex incorreto para divisão. Deveria ser"[^\\W_]"
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̷̨̰́̀ĥ̷̷̳̰̀ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳, o String.split(String regex)método usa um padrão que corresponde ao delimitador para dividir. Então, por exemplo, "aababba".split("b")renderia a matriz {"aa", "a", "", "a"}. Minha [^\\w\\d]expressão regular significa "um caractere nem nas classes de caracteres de palavra nem de dígito". [^\\W_]é "um caractere que não é um sublinhado nem está na classe de caracteres que não são palavras" e corresponderia a qualquer caractere de palavra, exceto o sublinhado.
AJMansfield

Desculpe, meu comentário anterior estava incorreto. \winclui \d, portanto, \dé redundante. \winclui sublinhado, que deve ser considerado um separador de acordo com a pergunta. Portanto, o regex correto para divisão deve ser "[\\W_]+".
N

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ ok, obrigado; Eu consertei o problema.
AJMansfield

17

APL (57)

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

por exemplo

      ⎕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

Explicação:

  • ⎕D,⎕A,⎕UCS 96+⍳26: números, letras maiúsculas, letras minúsculas
  • (I←⍞)∊: ler entrada, armazenar I, ver quais são alfanuméricos
  • Z←I⊂⍨: dividir Iem grupos de caracteres alfanuméricos, armazenar emZ
  • +⌿∘.≡⍨Z: para cada elemento Z, veja com que frequência ele ocorre
  • Z,⍪: corresponde a cada elemento em Z pares com quantas vezes ocorre
  • G←⊃∪↓: selecione apenas os pares únicos, armazene em G
  • ⍒,1↓⍉G: obtenha índices classificados para as ocorrências
  • G[... ;]: reordene as linhas de acordo Gcom os índices fornecidos

6
o que ... o ... f .....
Ozh 30/01

6
É por isso que tenho pesadelos.
Thebluefish

3
@Thebluefish: O APL foi projetado a partir de uma notação, com a intenção de que, assim como a matemática, uma notação concisa libera você para pensar com clareza. Novamente, como a matemática, quando você vê essa notação pela primeira vez, você tende a pensar que não é clara, mas as línguas sempre parecem complexas para começar. Seria mais fácil se não fosse tudo na mesma linha, embora ...
Phil H

o que quer que você invente no APL, vejo apenas lixo unicode, setas apontando nas direções e um pinheiro de cabeça para baixo. que é pior que J
bebe

Pode ser mais curto com ⎕s( help.dyalog.com/latest/Content/Language/System%20Functions/… ) e o novo operador principal ( 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 no modo "C # Statements", sem incluir a string de entrada)

Versão 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();

Ungolfed:

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

Versão 2: 114c

( [\w]inclui _, o que está incorreto ! ; [A-z]inclui [ \ ] ^ _ `; resolver [^_\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();

Ungolfed:

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 versão 1)


A propósito, para a versão 2, sua versão não-golfada não corresponde à sua versão para golfe. E como você está usando uma string literal, você pode escrever@"[^_\W]"
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ - corrigiu o erro de digitação e removeu o extra `` para uma economia de 1 caractere - obrigado !!
jimbobmcgee

7

R, 58 caracteres

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 

Isso é mais curto (49 caracteres) sort(table(gsub("[[:punct:]]","",scan(,""))),d=T). Infelizmente, ambas as soluções não funcionam corretamente wouldn't.
djhurio

6

perl6: 49 caracteres

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

Penteie a entrada para correspondência de itens \w+, coloque a lista resultante de palavras em umBag , peça seus pares e classifique-os por valor negativo. (A estrela *é o que quer que seja , não é multiplicação aqui)

saída:

"a" => 2
"This" => 1
"is" => 1
"text" => 1
"and" => 1
"number" => 1
"31" => 1

3
Perl 6 me assusta.
Primo

1
Toda vez que penso em um recurso interessante de linguagem, procuro por ele e está no Perl6 em algum lugar. É por isso que está demorando muito ...
Phil H

Você pode aparar 6 caracteres usando .wordsem vez de .comb(/\w+/):)
Mouq

@ Muq: infelizmente .wordsnão retira o :ou .da entrada conforme necessário :(
Ayiko 15/02/14

-1. _não deve ser incluído em uma palavra na declaração do 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)

Agora funciona com nova linha:

$ 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

Isso não funciona quando há novas linhas ou mais de um espaço consecutivo no texto.
Klingt.net

@ klingt.net corrigido.
Daniero 30/01

6

PHP - 84 bytes

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

A entrada é aceita como argumento de linha de comando, por exemplo:

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

Saída para a sequência de amostras:

Array
(
    [a] => 2
    [number] => 1
    [31] => 1
    [and] => 1
    [text] => 1
    [is] => 1
    [This] => 1
)

1
diz entrada é o que você deseja. para que você possa obtê-lo como parâmetro de linha de comando usando$argv[1]
Einacio 29/01

@Einacio boa chamada.
Primo

-1. Sublinhado _não deve ser incluído em uma palavra.
n̴̖̋h̷͉a̷̭̿h̸̡̅ẗ̵̨d̷̰ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ corrigido.
Primo 29/03

5

PowerShell (40)

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

$ s é uma variável que contém a sequência de entrada.


2
[\W]não é bom o suficiente - está correspondendo a um espaço no meu teste. E não é ordenada por descendente contagem ...
jimbobmcgee

$s -split"[\W]"|group -ca|where{$_.Name -ne ""}|sort{-$_.Count}você fica mais perto (com custos, é claro)
jimbobmcgee

Opa, perdi a parte da triagem. Corrigirei minha resposta em breve.
microbian

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

4
-split"\W+"está combinando uma sequência vazia entre o último .e o final da sequência; também \W+corresponde a _tecnicamente não permitido
jimbobmcgee 30/01

4

Perl 69

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

Recomendações adicionadas de @primo e @protist


1
E quanto à classificação?
Daniero 29/01

@daniero, excelente ponto! Isso agora classifica!
Dom Hastings

1
Eu acho que é o mais conciso possível. Se você não se importa com um aviso de descontinuação, não é necessário espaço entre gee for. Além disso, o <=>operador pode ser substituído por -.
Primo

2
@primo Ahhh, em -vez de <=>ser um gênio, não tenho certeza se isso está nas dicas de golfe do segmento Perl. Vou atualizar isso mais tarde, obrigado!
Dom Hastings

1
Hey @protist, também \winclui números ( perl -e 'print for"a 1 2 3 4 b"=~/\w/g'impressões a1234b), mas seu mecanismo de iteração das palavras salva outro caractere, então eu atualizarei. Obrigado!
Dom Hastings

4

Powershell: 57 55 53 62 57

(não incluindo a sequência de entrada)

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

retorna:

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}

(com adereços para @microbian para o grupo -ca)


3

EcmaScript 6

Versão 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]))

Versão 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]))

Versão 3 (105 caracteres)

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

Versão 4 (94 caracteres)

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

Versão 5 (sem alerta; 87 caracteres)

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

Versão 6 (100 caracteres)

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

Saída:

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

Você pode mudar _[a]e _[b]para _.ae _.b. Mudar também /\w+/g,_={}para _=/\w+/gproduzirá o mesmo resultado.
eithed

@eithedog Obrigado! No entanto, não posso mudar _[a]de ser _.aporque ele tenta acessar a propriedade "a"de _, não a propriedade a.
Escova de dentes

ah, correto - o pedido não será mantido. Continue :)
eithed

Oh, eu não percebi sua resposta .. legal. Mas .. está Object.keysse tornando global no ES6? Sua resposta parece assumir isso, mas não me lembro de ter visto isso como programado para o ES6.
FireFly

@ FireFly Não consigo encontrar nenhuma documentação, mas funciona bem no Firefox. Não testei no Chrome / Opera / IE.
Escova de dentes

3

Groovy 77 82

regex alterado de [^\w]+para [^\d\p{L}]+para resolver o problema com sublinhado

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}

sem primeira linha, 82 caracteres

saída:

[a:2, This:1, is:1, text:1, and:1, number:1, 31:1]

nu_bernão é alfanumérico. Este shouls ser 2 palavras
triturador

Por que usar em nu_bervez de number?
precisa saber é o seguinte

Fui enganado por algumas outras postagens;) agora removi o "_" da entrada, mas corrigi o regex para lidar com isso #
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

Embora gawk asorttrabalhe em matrizes associativas, aparentemente não preserva os valores do índice, necessitando dasort

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

Uma solução gawk um pouco maior, porém pura, usada PROCINFOpara definir a ordem de classificação padrão para o array associativo (parece exigir um gawk relativamente recente -> 4.x?)

BEGIN{RS="\\W+";PROCINFO["sorted_in"]="@val_num_desc"}
{c[$0]++}
END{for(w in c)print c[w],w}

Oooooh. Eu não sabia sobre o PROCINFO. Como se eu precisasse de outra desculpa para usar o awk na minha vida. Maldito seja!
dmckee

@dmckee TBH Eu não conhecia o PROCINFO até começar a bisbilhotar - eu estava convencido de que havia uma maneira de fazer o tipo de forma nativa - apenas uma pena que os identificadores sejam tão longos;)
steeldriver

Nos velhos tempos, simplesmente não havia uma maneira. O que leva a coisas como essa minha antiga resposta .
dmckee

-1. Sublinhado _não deve ser incluído em uma palavra.
n̴̖̋h̷͉a̷̭̿h̸̡̅ẗ̵̨d̷̰ĥ̷̳

3

Javascript - 132 126 caracteres!

(Código JS mais curto)

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

Melhorou a regex e algumas edições.


Ungolfed

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 = "Quão brilhante é este dia, não é, é"

=> [['é', 3],
['Como', 1],
['brilhante', 1],
['this', 1],
['day', 1],
['isn', 1] ,
['t', 1]]


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

Deu uma primeira tentativa no golfe. Feedback apreciado.


2

EcmaScript 6, 115 100 87 (sem prompt e alerta)

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.


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


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.


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


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().


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

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


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

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


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
$ 

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...



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

Separators will be anything that is not alpha-numeric - You only split on whitespace.
daniero


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

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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.