Conta le parole in un testo e visualizzale


26

Il codice dovrebbe inserire un testo (non obbligatorio può essere qualsiasi file, stdin, stringa per JavaScript, ecc.):

This is a text and a number: 31.

L'output deve contenere le parole con il loro numero di occorrenze, ordinate in base al numero di occorrenze in ordine decrescente:

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

Notare che 31 è una parola, quindi una parola è qualunque cosa alfanumerica, il numero non agisce come separatore, ad esempio si 0xAFqualifica come una parola. I separatori saranno tutto ciò che non è alfanumerico, inclusi .(punto) e -(trattino), i.e.oppure pick-me-upcomporterebbero 2 parole rispettivamente 3. Dovrebbe fare distinzione tra maiuscole Thise minuscole, e thissarebbero due parole diverse, 'sarebbe anche un separatore così wouldne tsaranno 2 parole diverse da wouldn't.

Scrivi il codice più breve nella tua lingua preferita.

La risposta corretta più breve finora:


5
Il caso è importante (ovvero è Thisuguale a thise tHIs)?
Gareth,

Se qualcosa di non alfanumerico conta come separatore, sono wouldn't2 parole ( wouldne t)?
Gareth,

@Gareth Dovrebbe fare distinzione tra maiuscole Thise minuscole, e thisin effetti sarebbero due parole diverse, stesse wouldne t.
Eduard Florinescu,

Se non ci fossero 2 parole, non dovrebbe essere "Would" e "nt" dato che è l'abbreviazione di Would not, o è troppo per la grammatica nazista?
Teun Pronk,

@TeunPronk Cerco di mantenerlo semplice, mettere alcune regole incoraggerà le eccezioni ad essere in ordine con la grammatica, e ci sono molte eccezioni là fuori. Ex in inglese i.e.è una parola ma se lasciamo il punto tutti i punti al la fine delle frasi sarà presa, lo stesso con le virgolette o le virgolette singole, ecc.
Eduard Florinescu,

Risposte:


27

grep e coreutils  44  42

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

Test:

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

Risultati in:

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

Aggiornare

  • Utilizzare l'opzione senza distinzione tra maiuscole e minuscole e regex più breve. Grazie Tomas.

2
Questo è quasi esattamente la risposta di McEllroy al libro Literate Programming di Knuth . L'unica differenza è che questo non include un pipe headalla fine.
AJMansfield,

Questo è stato praticamente anche il mio primo pensiero.
Rob,

1
Anche '\ w +' non funzionerebbe?
Sylwester,

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

1
@Tomas: aggiunto questo alla risposta, grazie. Ho lasciato la protezione per l'asterisco, perché espandeva i nomi dei file in alcune shell.
Thor,

18

Java 8: 289

Il che è abbastanza buono, dal momento che Java è un linguaggio molto non 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()));}

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

Esegui dalla riga di comando:

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

Regex errato per la divisione. Dovrebbe essere"[^\\W_]"
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳, il String.split(String regex)metodo prende uno schema che corrisponde al delimitatore su cui dividere. Quindi, per esempio, "aababba".split("b")produrrebbe l'array {"aa", "a", "", "a"}. La mia regex [^\\w\\d]significa "un personaggio né nella parola carattere né nelle classi di caratteri cifra". [^\\W_]è invece "un carattere che non è né un carattere di sottolineatura né che rientra nella classe di caratteri non di parole" e corrisponderebbe a qualsiasi carattere di parola tranne il carattere di sottolineatura.
AJMansfield,

Siamo spiacenti, il mio commento precedente non era corretto. \winclude \d, quindi \dè ridondante. \winclude il carattere di sottolineatura, che dovrebbe essere considerato un separatore in base alla domanda. Quindi dovrebbe essere la regex corretta per la divisione "[\\W_]+".
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ ok, grazie; Ho risolto il problema.
AJMansfield,

17

APL (57)

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

per esempio

      ⎕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

Spiegazione:

  • ⎕D,⎕A,⎕UCS 96+⍳26: numeri, lettere maiuscole, lettere minuscole
  • (I←⍞)∊: leggi input, archivia I, vedi quali sono alfanumerici
  • Z←I⊂⍨: diviso Iin gruppi di caratteri alfanumerici, memorizza inZ
  • +⌿∘.≡⍨Z: per ogni elemento in Z, vedi quanto spesso si verifica
  • Z,⍪: abbina ciascun elemento in Zcoppia con quante volte si verifica
  • G←⊃∪↓: seleziona solo le coppie uniche, memorizza in G
  • ⍒,1↓⍉G: ottiene indici ordinati per le occorrenze
  • G[... ;]: riordina le linee in Gbase agli indici indicati

6
cosa ... il ... f .....
Ozh

6
Questo è il motivo per cui ho incubi.
Pesce azzurro il

3
@Thebluefish: APL è stato progettato da una notazione, con l'intenzione che, proprio come la matematica, una notazione concisa ti consente di pensare chiaramente. Sempre come in matematica, quando vedi per la prima volta quella notazione, tendi a pensare che non sia affatto chiaro, ma le lingue sembrano sempre complesse all'inizio. Sarebbe più facile se non fosse tutto su una riga, però ...
Phil H,

qualunque cosa ti venga in mente in APL vedo solo un po 'di immondizia unicode, frecce che puntano in direzioni e un pino capovolto. che è peggio di J
bebe il

Potrebbe essere più breve con ⎕s( help.dyalog.com/latest/Content/Language/System%20Functions/… ) e il nuovo operatore chiave ( 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

(tramite LINQPad in modalità "Dichiarazioni C #", esclusa la stringa di input)

Versione 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

risultati:

risultati

Versione 2: 114c

( [\w]include _, che non è corretto ! ; [A-z]include [ \ ] ^ _ `; accontentarsi [^_\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

Risultati: (come versione 1)


A proposito, per la versione 2, la tua versione non golfata non corrisponde alla tua versione giocata a golf. E poiché stai usando una stringa letterale, puoi scrivere@"[^_\W]"
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ - risolto il refuso e rimosso il extra `` per un risparmio di 1 carattere - grazie !!
jimbobmcgee,

7

R, 58 caratteri

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 

Questo è più corto (49 caratteri) sort(table(gsub("[[:punct:]]","",scan(,""))),d=T). Sfortunatamente entrambe le soluzioni non funzionano correttamente wouldn't.
djhurio,

6

perl6: 49 caratteri

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

Combina l'input per roba corrispondente \w+, metti la lista risultante di parole in a Bag, chiedi le loro coppie e ordinale per valore negativo. (La *è una stella qualunque , qui non è la moltiplicazione)

produzione:

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

3
Perl 6 mi spaventa.
primo

1
Ogni volta che penso a una funzionalità linguistica interessante, la cerco ed è in Perl6 da qualche parte. Ecco perché ci vuole molto tempo ...
Phil H,

Puoi tagliare 6 caratteri usando .wordsinvece di .comb(/\w+/):)
Mouq

@Mouq: purtroppo .wordsnon elimina la :o .dall'ingresso come richiesto :(
Ayiko

-1. _non dovrebbe essere incluso in una parola nella dichiarazione 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)

Ora funziona con 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

Questo non funziona quando ci sono newline o più di uno spazio consecutivo nel testo.
klingt.net,

@ klingt.net riparato.
daniero,

6

PHP - 84 byte

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

L'input è accettato come argomento della riga di comando, ad esempio:

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

Output per la stringa di esempio:

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

1
dice che l'input è quello che vuoi. così puoi ottenerlo come parametro della riga di comando usando$argv[1]
Einacio

@Einacio buona chiamata.
primo

-1. Il carattere di sottolineatura _non deve essere incluso in una parola.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ risolto.
primo

5

PowerShell (40)

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

$ s è una variabile che contiene la stringa di input.


2
[\W]non è abbastanza buono - sta abbinando uno spazio nel mio test. E non è ordinato in base al conteggio decrescente ...
jimbobmcgee,

$s -split"[\W]"|group -ca|where{$_.Name -ne ""}|sort{-$_.Count}ti avvicina (con costi, ovviamente)
jimbobmcgee,

Spiacenti, ho perso la parte di smistamento. Risolverò la mia risposta a breve.
microbian

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

4
-split"\W+"sta abbinando una stringa vuota tra l'ultima .e la fine della stringa; anche \W+partite _che tecnicamente non sono ammesse
jimbobmcgee

4

Perl 69

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

Aggiunti consigli da @primo e @protist


1
Che dire dell'ordinamento?
daniero,

@daniero, punto eccellente! Questo adesso ordina!
Dom Hastings,

1
Penso che sia il più conciso possibile. Se non ti dispiace un avviso di deprecazione, non è richiesto spazio tra gee for. Inoltre, l' <=>operatore può essere sostituito da -.
primo

2
@primo Ahhh -invece di <=>genio, non sono sicuro che sia sui suggerimenti per il golf del thread Perl. Lo aggiornerò più tardi, grazie!
Dom Hastings,

1
Ehi @protista, \winclude anche i numeri ( perl -e 'print for"a 1 2 3 4 b"=~/\w/g'stampe a1234b), ma il tuo meccanismo per iterare le parole salva un altro personaggio, quindi aggiornerò. Grazie!
Dom Hastings,

4

Powershell: 57 55 53 62 57

(esclusa la stringa di input)

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

ritorna:

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 oggetti di scena a @microbian per il gruppo -ca)


3

EcmaScript 6

Versione 1 (108 caratteri)

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

Versione 2 (102 caratteri)

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

Versione 3 (105 caratteri)

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

Versione 4 (94 caratteri)

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

Versione 5 (senza avviso; 87 caratteri)

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

Versione 6 (100 caratteri)

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

Produzione:

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

Puoi cambiare _[a]e _[b]a _.ae _.b. Anche la modifica /\w+/g,_={}a _=/\w+/gprodurrà lo stesso risultato.
Eithed

@eithedog Grazie! Tuttavia, non posso cambiare _[a]per essere _.aperché tenta di accedere alla proprietà "a"di _, non alla proprietà a.
Spazzolino da denti

ah, corretto - l'ordine non verrà mantenuto. Continua :)
Eithed

Oh, non ho notato la tua risposta .. bello. Ma .. sta Object.keysdiventando un globale in ES6? La tua risposta sembra supporre questo, ma non ricordo di averlo visto come programmato per ES6.
FireFly,

@FireFly Non riesco a trovare alcuna documentazione, ma funziona bene in Firefox. Non l'ho testato in Chrome / Opera / IE.
Spazzolino da denti

3

Groovy 77 82

cambiato regex da [^\w]+a [^\d\p{L}]+per risolvere il problema con trattino basso

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}

senza prima riga, 82 caratteri

produzione:

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

nu_bernon è alfanumerico. Questo shouls deve essere di 2 parole
Cruncher,

Perché usare nu_berinvece di number?
Kevin Fegan,

Sono stato fuorviato da altri post;) ora ho rimosso il "_" dall'input, ma ho risolto il regex per gestirlo
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

Sebbene gawk asortlavori su array associativi, apparentemente non conserva i valori dell'indice, rendendo necessario l'esternosort

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 soluzione gawk leggermente più grande ma pura che utilizza PROCINFOper impostare l'ordinamento predefinito per l'array associativo (sembra richiedere un 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. Non sapevo di PROCINFO. Come se avessi bisogno di un'altra scusa per usare awk nella mia vita. Vi maledicono!
dmckee,

@dmckee TBH Non sapevo di PROCINFO fino a quando non ho iniziato a frugare in giro - ero convinto che ci doveva essere un modo per fare il tipo nativamente - solo un peccato che gli identificatori siano così lunghi;)
steeldriver

Ai vecchi tempi semplicemente non c'era modo. Il che porta a cose come questa mia vecchia risposta .
dmckee,

-1. Il carattere di sottolineatura _non deve essere incluso in una parola.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

3

Javascript - 132 126 caratteri!

(Codice JS più 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]})

Migliorata la regex e alcune modifiche.


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 = "Quanto è brillante oggi è non è"

=> [['is', 3],
['How', 1],
['shiny', 1],
['this', 1],
['day', 1],
['isn', 1] ,
['t', 1]]


Vecchio - 156 143 141 140 132 caratteri

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

Ho provato per la prima volta a golf. Feedback apprezzato.


2

EcmaScript 6, 115 100 87 (senza prompt e avviso)

Grazie 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 prompt e avviso (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]))

Eseguilo in Firefox.


1
Non hai bisogno var . Inoltre, puoi spostarti a={}all'interno prompt- prompt(a={}). Puoi anche rilasciarlo Object.e cambiarlo w=>a[w]=a[w]+1||1inw=>a[w]=-~a[w]
eithed

Molto bella. Batte subito il Python funzionante :)
teh_senaus,

Come per la risposta di @ toothbrush: spostare la dichiarazione ada prompt a regexp risparmierà altri due caratteri.
Eithed

È bello e pulito. Buon lavoro!
Spazzolino da denti

-1. Il carattere di sottolineatura _non deve essere incluso in una parola.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

2

Rubino 58 82 65

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

Prova:

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

Modifica 58-> 80: Ok, ero lontano. Ho dimenticato di ordinare le parole per occorrenza. Inoltre, Array#uniqnon è un enumeratore, ma utilizza un determinato blocco per confrontare gli elementi, quindi passare putsad esso non ha filtrato i duplicati (non che dice che dovremmo).


1
Forse split(/\W+/)invece di scan(non testato)?
Howard,

@ Grazie Grazie. \Wesclude _quindi che doveva essere corretto, ma ha comunque salvato 2 caratteri (quindi ho aggiunto 20 per correggere l'ordinamento che avevo trascurato).
daniero,

Non dovrebbe essere ordinato inreverse (a=gets.split(/[_\W]+/)).uniq.map{|w|[w,a.count(w)]}.sort_by(&:last).reverse.map{|x|p x}
Eduard Florinescu

@EduardFlorinescu Nah. reverseè troppo prolisso;) A proposito, non è giusto cambiare la domanda.
daniero,

Se si vede nell'esempio di output, è stato ordinato in modo discendente solo che ho dimenticato di specificarlo.
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"))

Uscita quando chiamato da 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 = ()

Aggiornamento: alcune spiegazioni come richiesto nei commenti.

Utilizza le funzioni set per generare una matrice di caratteri non alfanumerici nell'input da passare a String.Split, quindi utilizza le funzioni di sequenza per filtrare stringhe vuote, generare conteggi di parole e stampare il risultato.

Alcuni trucchi per il golf: aggiunge una stringa vuota all'argomento della funzione s per forzare l'inferenza del tipo dell'argomento come stringa anziché dichiarare esplicitamente il tipo. Utilizza Seq.where anziché Seq.filter per salvare alcuni caratteri (sono sinonimi). Mescola il forward pipe e l'applicazione delle normali funzioni nel tentativo di minimizzare i caratteri. Utilizza il curry e la sintassi (op) per trattare <> ~ - e <|| operatori come funzioni regolari per evitare di dichiarare lambdas per filtrare stringhe vuote, ordinarle in base al conteggio decrescente e stampare le tuple.


Dovresti assolutamente inserire una sorta di spiegazione; in questo modo possiamo capire il tuo codice.
Justin

Aggiunta una versione degolfata e alcune spiegazioni.
Mattnewport,

2

Python - 95 (ora 87 grazie a @primo)

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

Input di esempio:

'This is a text and a number: 31'

Uscita campione:

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

Qualsiasi suggerimento di miglioramento sarebbe apprezzato


1
La soluzione è buona ma l'output non è ordinato.
Eduard Florinescu,

Cosa intendi per ordinato? Grazie per il commento.
Azwr,

1
\wpartite [a-zA-Z0-9_]. L'intero regex può essere sostituito da r'\w+'. Inoltre, la xvariabile non è necessaria, basta usare raw_input()come secondo parametro per findall.
primo

Ordinato, l'OP significa che le parole che appaiono più spesso devono essere elencate per prime. Inoltre, il tuo programma dovrebbe includere una printdichiarazione (cioè print map(...), altrimenti non è un programma completo.
primo

Non ho tempo di ordinarlo adesso :( Ho fretta, grazie per i suggerimenti e i commenti.
Azwr

2

JavaScript 160 144 (modificato: per soddisfare i requisiti)

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

Registra ciascuna parola sulla console in ordine, passando la seguente stringa:

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

Uscite:

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 

Non ho il cuore da usare alert().


1
L'ordinamento dovrebbe essere in base al numero. di occorrenze quindi youdovrebbe essere il primo.
Eduard Florinescu,

@EduardFlorinescu Silly me ... La riparerò più tardi.
George Reith,

@EduardFlorinescu fixed
George Reith

-1. Il carattere di sottolineatura _non deve essere incluso in una parola.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

++o[a]||1=>-~o[a]
l4m2

2

k [71 caratteri]

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

Qualsiasi altro carattere tranne i caratteri alfanumerici verrà considerato come delimitatore.

esempio

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

esempio

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)

Esegue il ciclo su ogni possibile numero di corrispondenze in ordine decrescente e genera le parole con quel numero di occorrenze. Solo per essere orribile.

Note: l'avviso avrebbe ridotto la lunghezza di alcuni. A rigor di termini dovrebbe essere alfanumerico[^\W_]


2

Haskell (153 = 104 codice + 49 importazione)

Funzione abbastanza semplice, totalmente composta ... non è nemmeno necessario alcun argomento! Questo è il mio primo golf, quindi vai piano, forse? :)

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

Produzione:

*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 sostituisce non alfanumerico
  • "" vs divide il risultato in un elenco di simboli
  • conta ogni gruppo conta crea un dict abbinando elementi distinti della lista con il numero di occorrenze
  • desc ordina il dict in base a valori decrescenti

modifica: risolto accidentalmente abbinamenti ascii 58-64 e 91-96


1
Non ne ho conoscenza qma la regex è [0-z]basata su ASCII? In tal caso, non includerebbe anche i caratteri ASCII 58-64? Perché quelli lo sono : ; < = > ? @.
jimbobmcgee

Grande cattura jimbob, grazie
nightTrevors

Prego; notato solo perché ho trovato lo stesso in C #. Purtroppo, lo stesso con [A-z], che corrisponde a ASCII 91-96, che sono `[\] ^
_`

ah giusto, bella lezione ascii proprio lì!
nightTrevors

Ho appena scoperto il [^_\W]+mio, che dovrebbe essere "escludi caratteri non di parole e trattino basso" , se la tua sintassi supporta il\W classe ...
jimbobmcgee,

2

Pure Bash (nessun programma esterno), 164

Questo è più lungo di quanto sperassi, ma volevo vedere se il conteggio e l'ordinamento necessari (nella giusta direzione) potevano essere eseguiti esclusivamente con basharray (associativi e non associativi):

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

Salva come file di script chmod +xed esegui:

$ ./countoccur Questo è un testo e un numero: 31.
un: 2
e: 1
numero 1
testo: 1
31: 1
è: 1
Questo: 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-"}'

Fa il lavoro senza estensioni 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

Se invece stampa "count: word", sarebbe un po 'più breve ma volevo imitare l'output dell'esempio dato ...



1

Python 2.X (108 - Personaggi)

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

Python 3.X (106 - Personaggi)

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- Ti sei diviso solo su spazi bianchi.
daniero,


1

Python 3 - 76

L'obbligo di scissione su caratteri non alfanumerici sfortunatamente estende il codice di 19 caratteri. L'output di quanto segue è mostrato correttamente. Se non si è sicuri, aggiungere un .most_common()dopo il .Counter(...).

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

In / Output

Dato il tuo input This is a text and a number: 31.ottieni il seguente output:

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

L'ho provato con altri valori come

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

per garantire, l'ordine di output non si basa sul valore / hash della chiave. Questo esempio produce:

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

Ma come ho detto, print(i('collections').Counter(i('re').findall('\w+',input())).most_common())restituirei i risultati come un elenco di tuple definitivamente ordinato.


Python 3 - 57 (se uno spazio fosse sufficiente per la divisione: P)

print(__import__('collections').Counter(input().split()))

Se hai assunto che la stringa fosse in alcune variabili s, come fanno altre risposte, potresti perdere 6 caratteri sostituendo input ().
Phil H,

@PhilH bene. hai ragione, ma non lo leggerei mai dai requisiti. certo la parte "stringa per JavaScript" potrebbe suggerirlo, ma non posso, con una coscienza chiara, interpretare una variabile stringa come un "input" valido. Ma hai ragione. ciò lo accorcerebbe ancora di più. : P
Dave J,

-1. Il carattere di sottolineatura _non deve essere incluso in una parola.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

Bene, questo dipende dalla definizione di alfanumerico. In Python, "\ w" è definito per accettare caratteri alfanumerici. Potresti avere ragione, ma con questo tipo di interpretazione delle regole, la mia soluzione continua ad essere corretta. :)
Dave J,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.