Hitung kata-kata dalam sebuah teks dan tampilkan

26

Kode harus mengambil input teks (tidak wajib bisa berupa file apa pun, stdin, string untuk JavaScript, dll):

This is a text and a number: 31.

Output harus berisi kata-kata dengan jumlah kemunculannya, diurutkan berdasarkan jumlah kemunculan dalam urutan menurun:

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

Perhatikan bahwa 31 adalah kata, jadi kata adalah apa saja alfa-numerik, angka tidak bertindak sebagai pemisah sehingga misalnya 0xAFmemenuhi syarat sebagai kata. Pemisah akan berupa apa saja yang bukan alfanumerik termasuk .(titik) dan -(tanda hubung) dengan demikian i.e.atau pick-me-upakan menghasilkan 2 masing-masing 3 kata. Harus peka huruf besar-kecil, Thisdan thisakan menjadi dua kata yang berbeda, 'juga akan menjadi pemisah sehingga wouldndan takan menjadi 2 kata yang berbeda wouldn't.

Tulis kode terpendek dalam bahasa pilihan Anda.

Sejauh ini jawaban benar terpendek:

Eduard Florinescu
sumber
5
Apakah case case (yaitu Thissama dengan thisdan tHIs)?
Gareth
Jika sesuatu non-alfanumerik dianggap sebagai pemisah, apakah wouldn't2 kata ( wouldndan t)?
Gareth
@ Gareth Harus peka huruf besar-kecil, Thisdan thismemang akan dua kata yang berbeda, sama wouldndan t.
Eduard Florinescu
Jika bukankah 2 kata, bukankah seharusnya "Apakah" dan "tidak" karena kependekan dari Tidak, atau apakah itu terlalu banyak nazi-ish?
Teun Pronk
@TeunPronk saya mencoba untuk membuatnya tetap sederhana, meletakkan beberapa aturan akan mendorong pengecualian agar sesuai dengan tata bahasa, dan ada banyak pengecualian di luar sana. EX dalam bahasa Inggris i.e.adalah sebuah kata tetapi jika kita membiarkan titik semua titik di akhir frase akan diambil, sama dengan kutipan atau kutipan tunggal, dll.
Eduard Florinescu

Jawaban:

27

grep dan coreutils  44  42

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

Uji:

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

Hasil dalam:

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

Memperbarui

  • Gunakan opsi case-insensitive dan regex yang lebih pendek. Terima kasih Tomas.
Thor
sumber
2
Ini hampir persis respons McEllroy terhadap buku Knuth's Literate Programming . Satu-satunya perbedaan adalah bahwa ini tidak termasuk pipa ke headujung.
AJMansfield
Ini juga merupakan pemikiran pertama saya.
Rob
1
Bukankah '\ w +' juga berfungsi?
Sylwester
1
41 karakter :grep -io \[A-Z0-9]*|sort|uniq -c|sort -nr
Tomas
1
@ Thomas: Menambahkan ini ke jawabannya, terima kasih. Saya meninggalkan perlindungan untuk asterisk, karena itu memperluas nama file di beberapa shell.
Thor
18

Java 8: 289

Yang cukup bagus, karena java adalah bahasa yang sangat tidak 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()));}

Tidak Disatukan:

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

Jalankan dari baris perintah:

java -jar wordCounter.jar This is a text and a number: 31.
AJMansfield
sumber
Regex salah karena pemisahan. Seharusnya"[^\\W_]"
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳, String.split(String regex)metode ini mengambil pola yang cocok dengan pembatas untuk dipecah. Jadi, misalnya, "aababba".split("b")akan menghasilkan array {"aa", "a", "", "a"}. Regex saya [^\\w\\d]berarti 'karakter dalam karakter kata atau kelas karakter digit'. [^\\W_]sebaliknya 'karakter yang bukan garis bawah juga tidak ada di kelas non-karakter-karakter' dan akan cocok dengan karakter kata apa pun kecuali garis bawah.
AJMansfield
Maaf, komentar saya sebelumnya salah. \wtermasuk \d, begitu \djuga berlebihan. \wtermasuk garis bawah, yang harus dianggap sebagai pemisah sesuai dengan pertanyaan. Jadi regex yang benar untuk pemisahan harus "[\\W_]+".
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ ok, terima kasih; Saya sudah memperbaiki masalahnya.
AJMansfield
17

APL (57)

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

misalnya

      ⎕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

Penjelasan:

  • ⎕D,⎕A,⎕UCS 96+⍳26: angka, huruf besar, huruf kecil
  • (I←⍞)∊: baca input, simpan di I, lihat mana yang alfanumerik
  • Z←I⊂⍨: dibagi Idalam kelompok karakter alfanumerik, simpan diZ
  • +⌿∘.≡⍨Z: untuk setiap elemen dalam Z, lihat seberapa sering itu terjadi
  • Z,⍪: cocokkan setiap elemen secara Zberpasangan dengan berapa kali itu terjadi
  • G←⊃∪↓: pilih hanya pasangan unik, simpan di G
  • ⍒,1↓⍉G: dapatkan indeks yang diurutkan untuk kemunculannya
  • G[... ;]: menyusun ulang garis Gdengan indeks yang diberikan
marinus
sumber
6
apa ... yang ... f .....
Ozh
6
Inilah sebabnya saya punya mimpi buruk.
Thebluefish
3
@Thebluefish: APL dirancang dari notasi, dengan maksud yang mirip matematika, notasi singkat membuat Anda berpikir jernih. Sekali lagi seperti matematika, ketika Anda pertama kali melihat notasi itu, Anda cenderung berpikir itu tidak jelas sama sekali, tetapi bahasa selalu tampak rumit untuk memulai. Akan lebih mudah jika tidak semua dalam satu baris, ...
Phil H
apa pun yang Anda temukan di APL, saya hanya melihat beberapa unicode, panah menunjuk ke arah dan pohon pinus terbalik. itu lebih buruk dari J
bebe
Bisa lebih pendek dengan ⎕s( help.dyalog.com/latest/Content/Language/System%20Functions/… ) dan operator kunci baru ( 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 dalam mode "C # Statement", tidak termasuk string input)

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

Tidak Disatukan:

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

Hasil:

Hasil

Versi 2: 114c

( [\w]termasuk _, yang salah!; [A-z]termasuk [ \ ] ^ _ `; menyelesaikan [^_\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();

Tidak Disatukan:

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

Hasil: (seperti Versi 1)

jimbobmcgee
sumber
Ngomong-ngomong, untuk versi 2, versi ungolfed Anda tidak cocok dengan versi golf Anda. Dan karena Anda menggunakan string literal, Anda dapat menulis@"[^_\W]"
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ - memperbaiki kesalahan ketik dan menghapus `` ekstra untuk penghematan 1-ar - terima kasih !!
jimbobmcgee
7

R, 58 char

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

Pemakaian:

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
sumber
Ini lebih pendek (49 karakter) sort(table(gsub("[[:punct:]]","",scan(,""))),d=T). Sayangnya kedua solusi tidak berfungsi dengan benar wouldn't.
djhurio
6

perl6: 49 karakter

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

Sisir input untuk pencocokan barang \w+, masukkan daftar kata yang dihasilkan di a Bag, minta pasangan mereka dan urutkan berdasarkan nilai negatif. (The *adalah bintang Apapun , ini bukan perkalian di sini)

keluaran:

"a" => 2
"This" => 1
"is" => 1
"text" => 1
"and" => 1
"number" => 1
"31" => 1
Ayiko
sumber
3
Perl 6 membuatku takut.
Primo
1
Setiap kali saya memikirkan fitur bahasa yang keren, saya mencarinya dan ada di Perl6 di suatu tempat. Itu sebabnya butuh waktu lama ...
Phil H
Anda dapat memangkas 6 karakter dengan menggunakan .wordsalih-alih .comb(/\w+/):)
Mouq
@Mouq: sayangnya .wordstidak menghapus :atau .dari input yang diperlukan :(
Ayiko
-1. _seharusnya tidak dimasukkan dalam kata di bawah pernyataan masalah.
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)

Sekarang berfungsi dengan baris baru:

$ 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
sumber
Ini tidak berfungsi ketika ada baris baru atau lebih dari satu ruang berurutan dalam teks.
klingt.net
@ klingt.net diperbaiki.
daniero
6

PHP - 84 byte

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

Input diterima sebagai argumen baris perintah, misalnya:

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

Output untuk string sampel:

Array
(
    [a] => 2
    [number] => 1
    [31] => 1
    [and] => 1
    [text] => 1
    [is] => 1
    [This] => 1
)
primo
sumber
1
ia mengatakan input adalah apa yang Anda inginkan. sehingga Anda bisa mendapatkannya sebagai parameter baris perintah menggunakan$argv[1]
Einacio
@Einacio panggilan yang bagus.
Primo
-1. Garis bawah _tidak harus dimasukkan dalam kata.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ diperbaiki.
Primo
5

PowerShell (40)

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

$ s adalah variabel yang berisi string input.

mikrobia
sumber
2
[\W]tidak cukup baik - ini cocok dengan ruang dalam pengujian saya. Dan itu tidak diperintahkan oleh hitungan menurun ...
jimbobmcgee
$s -split"[\W]"|group -ca|where{$_.Name -ne ""}|sort{-$_.Count}membuat Anda lebih dekat (dengan biaya, tentu saja)
jimbobmcgee
Ups, aku merindukan bagian penyortiran. Akan segera memperbaiki jawaban saya.
microbian
sebagai alternatif:$s -split"\W+"|group -ca |sort count -des
Nacimota
4
-split"\W+"mencocokkan string kosong antara yang terakhir .dan yang terakhir dari string; juga \W+pertandingan _yang secara teknis tidak diizinkan
jimbobmcgee
4

Perl 69

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

Rekomendasi tambahan dari @primo dan @protist

Dom Hastings
sumber
1
Bagaimana dengan penyortiran?
daniero
@daniero, poin bagus! Ini sekarang macam!
Dom Hastings
1
Saya pikir itu tentang singkat seperti yang bisa didapat. Jika Anda tidak keberatan dengan peringatan penghentian, tidak ada ruang yang diperlukan antara gedan for. Selain itu, <=>operator dapat diganti oleh -.
Primo
2
@ primo Ahhh -bukannya <=>jenius, tidak yakin itu ada di tips golf untuk Perl thread. Saya akan memperbarui ini nanti, terima kasih!
Dom Hastings
1
Hai @protist, \wsertakan juga angka ( perl -e 'print for"a 1 2 3 4 b"=~/\w/g'cetakan a1234b), tetapi mekanisme Anda untuk mengulangi kata-kata menyimpan karakter lain jadi saya akan memperbarui. Terima kasih!
Dom Hastings
4

Powershell: 57 55 53 62 57

(tidak termasuk string input)

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

pengembalian:

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}

(dengan alat peraga ke @ microbian untuk grup -ca)

jimbobmcgee
sumber
3

EcmaScript 6

Versi 1 (108 karakter)

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

Versi 2 (102 karakter)

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

Versi 3 (105 karakter)

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

Versi 4 (94 karakter)

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

Versi 5 (tanpa peringatan; 87 karakter)

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

Versi 6 (100 karakter)

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

Keluaran:

a:2
31:1
This:1
is:1
text:1
and:1
number:1
Sikat gigi
sumber
Anda dapat mengubah _[a]dan _[b]ke _.adan _.b. Juga berubah /\w+/g,_={}untuk _=/\w+/gakan menghasilkan hasil yang sama.
eithed
@eithedog Terima kasih! Namun, saya tidak bisa mengubah _[a]menjadi _.akarena mencoba untuk mengakses properti "a"dari _, tidak properti a.
Sikat gigi
ah, benar - pesanan tidak akan disimpan. Lanjutkan :)
eithed
Oh, saya tidak memperhatikan jawaban Anda .. bagus. Tapi .. apakah Object.keysmenjadi global dalam ES6? Jawaban Anda tampaknya menganggap ini, tapi saya tidak ingat melihatnya sesuai jadwal untuk ES6.
FireFly
@ FireFly Saya tidak dapat menemukan dokumentasi apa pun, tetapi berfungsi dengan baik di Firefox. Saya belum mengujinya di Chrome / Opera / IE.
Sikat gigi
3

Groovy 77 82

mengubah regex dari [^\w]+menjadi [^\d\p{L}]+untuk menyelesaikan masalah dengan garis bawah

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}

tanpa baris pertama, 82 karakter

keluaran:

[a:2, This:1, is:1, text:1, and:1, number:1, 31:1]
Kamil Mikolajczyk
sumber
nu_berbukan alfanumerik. Ini akan menjadi 2 kata
Cruncher
Kenapa menggunakan nu_berbukan number?
Kevin Fegan
Saya disesatkan oleh beberapa posting lain;) sekarang saya menghapus "_" dari input, tetapi memperbaiki regex untuk menanganinya
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

Meskipun gawk asortbekerja pada array asosiatif, itu tampaknya tidak mempertahankan nilai indeks, mengharuskan eksternalsort

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

Solusi gawk yang sedikit lebih besar tetapi murni menggunakan PROCINFOuntuk mengatur urutan sortir default untuk array asosiatif (tampaknya membutuhkan gawk yang relatif baru -> 4.x?)

BEGIN{RS="\\W+";PROCINFO["sorted_in"]="@val_num_desc"}
{c[$0]++}
END{for(w in c)print c[w],w}
Steeldriver
sumber
Oooooh. Saya tidak tahu tentang PROCINFO. Seolah aku butuh alasan lain untuk menggunakan awk dalam hidupku. Terkutuklah kamu!
dmckee
@ dmckee TBH Saya tidak tahu tentang PROCINFO sampai saya mulai mencari-cari - saya yakin harus ada cara untuk melakukan semacam itu secara asli - hanya sayang pengidentifikasi begitu lama;)
steeldriver
Di masa lalu yang buruk tidak ada jalan. Yang mengarah ke hal-hal seperti ini jawaban lama saya .
dmckee
-1. Garis bawah _tidak harus dimasukkan dalam kata.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
3

Javascript - 132 126 karakter!

(Kode JS terpendek)

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

Memperbaiki regex dan beberapa pengeditan.


Tidak disatukan

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 = "Betapa mengkilapnya hari ini?"

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


Tua - 156 143 141 140 132 karakter

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

Memberi percobaan golf yang pertama. Umpan balik dihargai.

Gaurang Tandon
sumber
2

EcmaScript 6, 115 100 87 (tanpa peringatan & peringatan)

Terima kasih kepada @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])

Dengan cepat dan waspada (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]))

Jalankan di Firefox.

teh_senaus
sumber
1
Anda tidak perlu var . Anda juga dapat pindah ke a={}dalam prompt- prompt(a={}). Anda juga dapat drop Object.dan ganti w=>a[w]=a[w]+1||1kew=>a[w]=-~a[w]
eithed
Sangat bagus. Mengalahkan Python yang berfungsi sekarang :)
teh_senaus
Sama seperti untuk jawaban @ toothbrush - memindahkan deklarasi adari prompt ke regexp akan menyimpan dua karakter lagi.
eithed
Bagus dan bersih. Kerja bagus!
Sikat gigi
-1. Garis bawah _tidak harus dimasukkan dalam kata.
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}

Uji coba:

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

Sunting 58-> 80: Oke, saya tidak ada. Saya lupa mengurutkan kata berdasarkan kejadian. Selain itu, Array#uniqbukan enumerator, tetapi menggunakan blok yang diberikan untuk membandingkan elemen, jadi meneruskannya putstidak menyaring duplikat (bukan berarti ia harus melakukannya).

daniero
sumber
1
Mungkin split(/\W+/)bukannya scan(belum diuji)?
Howard
@Howard, terima kasih. \Wmengecualikan _sehingga harus diperbaiki, tetapi masih menyimpan 2 karakter (kemudian saya menambahkan 20 untuk memperbaiki penyortiran yang telah saya abaikan).
daniero
Seharusnya tidak diurutkan dalamreverse (a=gets.split(/[_\W]+/)).uniq.map{|w|[w,a.count(w)]}.sort_by(&:last).reverse.map{|x|p x}
Eduard Florinescu
@EduardFlorinescu Nah. reverseterlalu verbose;) Btw, itu tidak adil mengubah pertanyaan.
daniero
Jika Anda melihat dalam sampel output, ia hanya diurutkan dan saya lupa untuk menentukannya.
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"))

Diturunkan:

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 ketika dipanggil dari 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 = ()

Perbarui: Beberapa penjelasan seperti yang diminta dalam komentar.

Menggunakan fungsi yang ditetapkan untuk menghasilkan array karakter non-alfanumerik di input untuk diteruskan ke String.Split, lalu menggunakan fungsi urutan untuk menyaring string kosong, menghasilkan jumlah kata, dan mencetak hasilnya.

Beberapa trik bermain golf: Menambahkan string kosong ke argumen fungsi s untuk memaksa inferensi tipe argumen sebagai string daripada secara eksplisit menyatakan jenisnya. Menggunakan Seq.where daripada Seq.filter untuk menyimpan beberapa karakter (mereka adalah sinonim). Memadukan pipa maju dan aplikasi fungsi biasa dalam upaya meminimalkan karakter. Menggunakan sintaksis currying dan (op) untuk menangani <> ~ - dan <|| operator sebagai fungsi biasa untuk menghindari menyatakan lambdas untuk memfilter string kosong, urutkan berdasarkan jumlah yang menurun dan mencetak tupel.

mattnewport
sumber
Anda harus memasukkan semacam penjelasan; dengan begitu kami dapat memahami kode Anda.
Justin
Menambahkan versi degolfed dan beberapa penjelasan.
mattnewport
2

Python - 95 (sekarang 87 berkat @primo)

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

Input sampel:

'This is a text and a number: 31'

Output sampel:

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

Saran perbaikan apa pun akan dihargai

Azwr
sumber
1
Solusinya bagus tetapi hasilnya tidak diurutkan.
Eduard Florinescu
Apa yang Anda maksud dengan diurutkan? Terima kasih atas komentarnya.
Azwr
1
\wcocok [a-zA-Z0-9_]. Seluruh regex Anda dapat digantikan oleh r'\w+'. Juga, xvariabel tidak diperlukan, cukup gunakan raw_input()sebagai parameter kedua findall.
Primo
Dengan diurutkan, OP berarti bahwa kata-kata yang muncul paling sering harus didaftar terlebih dahulu. Juga, program Anda harus menyertakan printpernyataan (yaitu print map(...), kalau tidak itu bukan program yang lengkap.
primo
Saya tidak punya waktu untuk mengatasinya sekarang :( Saya sedang terburu-buru, terima kasih atas saran dan komentarnya.
Azwr
2

JavaScript 160 144 (Diedit: untuk memenuhi persyaratan)

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

Tidak dijinakkan:

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

Log setiap kata ke konsol dalam urutan, melewati string berikut:

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

Output:

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 

Saya tidak punya hati untuk digunakan alert().

George Reith
sumber
1
Jenisnya harus berdasarkan nomor. kejadian jadi youharus menjadi yang pertama.
Eduard Florinescu
@EduardFlorinescu Silly saya ... Saya akan memperbaikinya nanti.
George Reith
@EduardFlorinescu diperbaiki
George Reith
-1. Garis bawah _tidak harus dimasukkan dalam kata.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
++o[a]||1=>-~o[a]
l4m2
2

k [71 karakter]

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

Karakter lain apa pun kecuali karakter alfanumerik akan dianggap sebagai pembatas.

contoh

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

contoh

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

Tidak dijinakkan:

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)

Ulangi setiap kemungkinan jumlah kecocokan dalam urutan menurun, dan keluarkan kata-kata dengan jumlah kemunculan itu. Hanya untuk menjadi mengerikan.

Catatan: Peringatan akan mengurangi panjangnya. Seharusnya alfanumerik berbicara[^\W_]

Zachary Vance
sumber
2

Haskell (153 = 104 kode + 49 impor)

Cukup mudah, fungsi yang sepenuhnya tersusun ... bahkan tidak perlu ada argumen! Ini golf pertama saya, jadi mudah saja, mungkin? :)

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

Keluaran:

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

q (50)

desc count each group" "vs ssr[;"[^0-9A-Za-z]";" "]
  • ssr menggantikan bukan alfanumerik
  • "" vs membagi hasil menjadi daftar simbol
  • menghitung setiap jumlah kelompok membuat dict yang cocok dengan elemen yang berbeda dari daftar dengan jumlah kejadian
  • desc mengurutkan dict dengan menurunkan nilai

sunting: diperbaiki secara tidak sengaja ascii cocok 58-64 dan 91-96

nightTrevors
sumber
1
Saya tidak memiliki pengetahuan tentang qtetapi apakah [0-z]ASCII berbasis regex ? Jika ya, bukankah itu juga termasuk karakter ASCII 58-64? Karena itu : ; < = > ? @.
jimbobmcgee
Jimbob tangkapan hebat, terima kasih
nightTrevors
Sama-sama; hanya terlihat karena saya menemukan hal yang sama di C #. Sedihnya, sama dengan [A-z], yang cocok dengan ASCII 91-96, yaitu `[\] ^
_`
ah benar, pelajaran ascii kecil yang menyenangkan di sana!
nightTrevors
Saya baru saja menemukan [^_\W]+untuk saya, yang harus "mengecualikan karakter non-kata dan garis bawah" , jika sintaks Anda mendukung \Wkelas ...
jimbobmcgee
2

Pure Bash (tidak ada program eksternal), 164

Ini lebih lama daripada yang saya harapkan, tetapi saya ingin melihat apakah penghitungan dan penyortiran yang diperlukan (ke arah yang benar) dapat dilakukan secara murni dengan basharray (asosiatif dan non-asosiatif):

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

Simpan sebagai file skrip chmod +x,, dan jalankan:

$ ./countoccur Ini adalah teks dan angka: 31.
a: 2
dan 1
nomor 1
teks: 1
31: 1
adalah: 1
Ini: 1
$ 
Trauma Digital
sumber
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-"}'

Apakah pekerjaan tanpa ekstensi 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

Jika mencetak "count: word" sebagai gantinya, itu akan menjadi sedikit lebih pendek tapi saya ingin meniru contoh output yang diberikan ...


sumber
2

Tcl , 99 byte

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

Cobalah online!

sergiol
sumber
1

Python 2.X (108 - Karakter)

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

Python 3.X (106 - Karakter)

print('\n'.join('{}:{}'.format(a,b)for a,b in __import__("collections").Counter(input().split()).items())
Abhijit
sumber
Separators will be anything that is not alpha-numeric- Anda hanya terpecah di spasi putih.
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
sumber
Tidak memenuhi ketentuan bahwa non-alfanumerik harus menjadi pemisah.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
1

Python 3 - 76

Persyaratan pemisahan pada karakter non-alfanumerik sayangnya menambah kode sebanyak 19 karakter. Output dari berikut ini ditampilkan dengan benar. Jika Anda tidak yakin, tambahkan .most_common()setelah .Counter(...).

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

In / Output

Diberikan input dari This is a text and a number: 31.Anda mendapatkan output berikut:

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

Saya mencobanya dengan nilai-nilai lain seperti

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

untuk memastikan, output-order tidak bergantung pada nilai / hash kunci. Contoh ini menghasilkan:

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

Tapi seperti yang saya katakan, print(i('collections').Counter(i('re').findall('\w+',input())).most_common())akan mengembalikan hasilnya sebagai daftar tupel yang dipesan secara pasti .


Python 3 - 57 (jika spasi cukup untuk pemisahan: P)

print(__import__('collections').Counter(input().split()))
Dave J
sumber
Jika Anda mengasumsikan string dalam beberapa variabel, seperti beberapa jawaban lainnya, Anda dapat kehilangan 6 karakter dengan mengganti input ().
Phil H
@PhilH well. Anda benar, tetapi saya tidak akan pernah membacanya dari persyaratan. yakin bagian "string untuk JavaScript" mungkin menyarankannya, tapi saya tidak bisa, dengan hati nurani yang jelas, menafsirkan variabel string sebagai "input" yang valid. Tapi kamu benar. itu akan mempersingkat bahkan lebih. : P
Dave J
-1. Garis bawah _tidak harus dimasukkan dalam kata.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
Yah ini tergantung pada definisi alpha-numeric. Dalam Python, "\ w" didefinisikan untuk menerima karakter alfa-numerik. Anda mungkin benar tetapi dengan interpretasi aturan semacam ini, solusi saya tetap benar. :)
Dave J