Đếm các từ trong một văn bản và hiển thị chúng


26

Mã phải nhập văn bản (không bắt buộc có thể là bất kỳ tệp nào, stdin, chuỗi cho JavaScript, v.v.):

This is a text and a number: 31.

Đầu ra phải chứa các từ có số lần xuất hiện của chúng, được sắp xếp theo số lần xuất hiện theo thứ tự giảm dần:

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

Lưu ý rằng 31 là một từ, vì vậy một từ là bất kỳ số alpha, số nào không đóng vai trò là dấu phân cách, ví dụ như 0xAFđủ điều kiện là một từ. Dấu phân cách sẽ là bất cứ thứ gì không phải là số alpha bao gồm .(dấu chấm) và -(dấu gạch nối) do đó i.e.hoặc pick-me-upsẽ dẫn đến 2 từ tương ứng 3 từ. Nên phân biệt chữ hoa chữ thường Thisthissẽ là hai từ khác nhau, 'cũng sẽ là dấu phân cách wouldntsẽ là 2 từ khác nhau wouldn't.

Viết mã ngắn nhất trong ngôn ngữ của bạn lựa chọn.

Câu trả lời đúng ngắn nhất cho đến nay:


5
Liệu trường hợp có vấn đề (tức là Thisgiống như thistHIs)?
Gareth

Nếu bất cứ thứ gì không phải là chữ và số được tính là dấu phân cách, thì có wouldn't2 từ ( wouldnt) không?
Gareth

@Gareth Nên phân biệt chữ hoa chữ thường Thisthisthực sự là hai từ khác nhau, giống nhau wouldnt.
Eduard Florinescu

Nếu không phải là 2 từ, thì không nên là "Sẽ" và "nt" vì nó là viết tắt của Từ không, hoặc đó có phải là nhiều ngữ pháp nazi-ish không?
Teun Pronk

@TeunPronk Tôi cố gắng giữ cho nó đơn giản, đặt một vài quy tắc sẽ khuyến khích các ngoại lệ theo thứ tự ngữ pháp và có rất nhiều trường hợp ngoại lệ .Ex trong tiếng Anh i.e.là một từ nhưng nếu chúng ta để dấu chấm ở tất cả các dấu chấm tại cuối cụm từ sẽ được thực hiện, cùng với dấu ngoặc kép hoặc dấu ngoặc đơn, v.v.
Eduard Florinescu

Câu trả lời:


27

grep và coreutils  44  42

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

Kiểm tra:

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

Kết quả trong:

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

Cập nhật

  • Sử dụng tùy chọn không phân biệt chữ hoa chữ thường và regex ngắn hơn. Cảm ơn anh.

2
Đây gần như chính xác là phản ứng của McEllroy đối với cuốn sách Lập trình văn học của Knuth . Sự khác biệt duy nhất là điều này không bao gồm một đường ống vào headcuối.
AJMansfield

Đây cũng là suy nghĩ đầu tiên của tôi.
Rob

1
Sẽ không '\ w +' hoạt động tốt chứ?
Sylwester

1
41 nhân vật :grep -io \[A-Z0-9]*|sort|uniq -c|sort -nr
Tomas

1
@Tomas: Đã thêm điều này vào câu trả lời, cảm ơn. Tôi để lại sự bảo vệ cho dấu hoa thị, vì nó đang mở rộng tên tệp trong một số shell.
Thor

18

Java 8: 289

Điều này là khá tốt, vì java là một ngôn ngữ không phải là 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()));}

Ung dung:

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

Chạy từ dòng lệnh:

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

Regex sai cho tách. Nó sẽ là"[^\\W_]"
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳, String.split(String regex)phương thức lấy một mẫu phù hợp với dấu phân cách để phân tách. Vì vậy, ví dụ, "aababba".split("b")sẽ mang lại mảng {"aa", "a", "", "a"}. Regex của tôi [^\\w\\d]có nghĩa là 'một ký tự trong các lớp ký tự không phải là ký tự chữ số'. [^\\W_]thay vào đó, 'một ký tự không phải là dấu gạch dưới cũng không thuộc lớp không có ký tự' và sẽ khớp với bất kỳ ký tự từ nào ngoại trừ dấu gạch dưới.
AJMansfield

Xin lỗi, nhận xét trước đây của tôi là không chính xác. \wbao gồm \d, như vậy \dlà dư thừa. \wbao gồm gạch dưới, nên được coi là một dấu phân cách theo câu hỏi. Vì vậy, regex chính xác để chia tách nên được "[\\W_]+".
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ ok, cảm ơn; Tôi đã khắc phục sự cố.
AJMansfield

17

APL (57)

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

ví dụ

      ⎕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

Giải trình:

  • ⎕D,⎕A,⎕UCS 96+⍳26: số, chữ hoa, chữ thường
  • (I←⍞)∊: đọc đầu vào, lưu trữ I, xem cái nào là chữ và số
  • Z←I⊂⍨: chia Ithành các nhóm ký tự chữ và số, lưu trữ trongZ
  • +⌿∘.≡⍨Z: cho mỗi phần tử trong Z, xem tần suất xảy ra
  • Z,⍪: khớp từng phần tử Ztheo cặp với số lần xuất hiện
  • G←⊃∪↓: chỉ chọn các cặp duy nhất, lưu trữ trong G
  • ⍒,1↓⍉G: nhận các chỉ số được sắp xếp cho các lần xuất hiện
  • G[... ;]: Sắp xếp lại các dòng của Gcác chỉ số đã cho

6
cái gì ... cái ... f .....
Ozh

6
Đây là lý do tại sao tôi gặp ác mộng.
Thebluefish

3
@Thebluefish: APL được thiết kế từ một ký hiệu, với ý định rất giống toán học, một ký hiệu ngắn gọn giải phóng bạn để suy nghĩ rõ ràng. Một lần nữa giống như toán học, khi bạn lần đầu tiên nhìn thấy ký hiệu đó, bạn có xu hướng nghĩ rằng nó không rõ ràng chút nào, nhưng ngôn ngữ luôn có vẻ phức tạp để bắt đầu. Sẽ dễ dàng hơn nếu đó không phải là tất cả trên một dòng, mặc dù ...
Phil H

bất cứ điều gì bạn nghĩ ra trong APL tôi chỉ thấy một số rác unicode, mũi tên chỉ vào hướng và một cây thông lộn ngược. điều đó còn tệ hơn J
bebe

Có thể ngắn hơn với ⎕s( help.dyalog.com/latest/Content/L Language / System% 20Fiances / Thay ) và toán tử khóa mới ( help.dyalog.com/latest/Content/Lingu/Primitive%20Operators/ tựa ):g⌷⍨⊂⍒2⌷⍉g←{⍺,≢⍵}⌸('\w+'⎕s'\0')⍞
ngn

8

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

(thông qua LINQPad trong chế độ "Báo cáo C #", không bao gồm chuỗi đầu vào)

Phiên bả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();

Ung dung:

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

Các kết quả:

Các kết quả

Phiên bản 2: 114c

( [\w]bao gồm _, không chính xác!; [A-z]bao gồm [ \ ] ^ _ `; giải quyết [^_\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();

Ung dung:

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

Kết quả: (như Phiên bản 1)


Nhân tiện, đối với phiên bản 2, phiên bản không có người nhận của bạn không phù hợp với phiên bản chơi gôn của bạn. Và vì bạn đang sử dụng chuỗi ký tự, bạn có thể viết@"[^_\W]"
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ - đã sửa lỗi chính tả và xóa thêm `` để tiết kiệm 1 ký tự - cảm ơn !!
jimbobmcgee

7

R, 58 char

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

Sử dụng:

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 

Cái này ngắn hơn (49 ký tự) sort(table(gsub("[[:punct:]]","",scan(,""))),d=T). Thật không may, cả hai giải pháp đều không hoạt động chính xác wouldn't.
djhurio

6

perl6: 49 ký tự

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

Kết hợp đầu vào cho công cụ khớp \w+, đặt danh sách các từ kết quả vào a Bag, yêu cầu các cặp của chúng và sắp xếp chúng theo giá trị âm. (Ngôi sao * , nó không nhân lên ở đây)

đầu ra:

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

3
Perl 6 làm tôi sợ.
Primo

1
Mỗi khi tôi nghĩ về một tính năng ngôn ngữ thú vị, tôi tìm kiếm nó và nó ở Perl6 ở đâu đó. Đó là lý do tại sao phải mất một thời gian dài ...
Phil H

Bạn có thể cắt 6 ký tự bằng cách sử dụng .wordsthay vì .comb(/\w+/):)
Mouq

@Mouq: không may .wordskhông loại bỏ :hoặc .từ đầu vào theo yêu cầu :(
Ayiko

-1. _không nên được bao gồm trong một từ theo tuyên bố vấn đề.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

6

Con trăn 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)

Bây giờ hoạt động với dòng mới:

$ 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

Điều này không hoạt động khi có dòng mới hoặc nhiều hơn một khoảng trắng trong văn bản.
klingt.net

@ klingt.net đã sửa.
daniero

6

PHP - 84 byte

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

Đầu vào được chấp nhận làm đối số dòng lệnh, ví dụ:

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

Đầu ra cho chuỗi mẫu:

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

1
Nó nói đầu vào là những gì bạn muốn. vì vậy bạn có thể lấy nó làm tham số dòng lệnh bằng cách sử dụng$argv[1]
Einacio

@Einacio gọi tốt.
primo

-1. Gạch dưới _không nên được bao gồm trong một từ.
n̴̖̋h̷͉a̷̭̿h̸̡̅ẗ̵̨d̷̰ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ đã sửa.
Primo

5

PowerShell (40)

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

$ s là một biến chứa chuỗi đầu vào.


2
[\W]không đủ tốt - nó phù hợp với một không gian trong thử nghiệm của tôi. Và nó không được ra lệnh bằng cách giảm dần ...
jimbobmcgee

$s -split"[\W]"|group -ca|where{$_.Name -ne ""}|sort{-$_.Count}giúp bạn gần gũi hơn (với chi phí, tất nhiên)
jimbobmcgee

Ooops tôi đã bỏ lỡ phần sắp xếp. Sẽ sửa câu trả lời của tôi trong thời gian ngắn.
microbian

cách khác:$s -split"\W+"|group -ca |sort count -des
Nacimota

4
-split"\W+"đang khớp một chuỗi trống giữa cuối .và cuối chuỗi; cũng \W+phù hợp _về mặt kỹ thuật không được phép
jimbobmcgee

4

Perl 69

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

Đã thêm đề xuất từ ​​@primo và @protist


1
Còn việc sắp xếp thì sao?
daniero

@daniero, điểm tuyệt vời! Điều này bây giờ sắp xếp!
Dom Hastings

1
Tôi nghĩ đó là về những gì ngắn gọn như nó có thể nhận được. Nếu bạn không nhớ cảnh báo không dùng nữa, không có khoảng trống nào được yêu cầu giữa gefor. Ngoài ra, các <=>nhà điều hành có thể được thay thế bởi -.
Primo

2
@primo Ahhh -thay vì <=>là thiên tài, không chắc đó là mẹo chơi golf cho chủ đề Perl. Tôi sẽ cập nhật điều này sau, cảm ơn!
Dom Hastings

1
Xin chào @protist, \wbao gồm cả số ( perl -e 'print for"a 1 2 3 4 b"=~/\w/g'in a1234b), nhưng cơ chế lặp lại các từ của bạn sẽ lưu một ký tự khác để tôi cập nhật. Cảm ơn bạn!
Dom Hastings

4

Quyền hạn: 57 55 53 62 57

(không bao gồm chuỗi đầu vào)

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

trả về:

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}

(có đạo cụ cho @microbian cho nhóm -ca)


3

EcmaScript 6

Phiên bản 1 (108 ký tự)

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

Phiên bản 2 (102 ký tự)

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

Phiên bản 3 (105 ký tự)

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

Phiên bản 4 (94 ký tự)

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

Phiên bản 5 (không có cảnh báo; 87 ký tự)

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

Phiên bản 6 (100 ký tự)

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

Đầu ra:

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

Bạn có thể thay đổi _[a]_[b]đến _.a_.b. Cũng thay đổi /\w+/g,_={}để _=/\w+/gtạo ra kết quả tương tự.

@eithedog Cảm ơn bạn! Tuy nhiên, tôi không thể thay đổi _[a]_.avì nó cố gắng truy cập vào tài sản "a"của _, chứ không phải tài sản a.
Bàn chải đánh răng

ah, đúng - thứ tự sẽ không được giữ. Tiếp tục :)

Oh, tôi đã không nhận thấy câu trả lời của bạn .. tốt đẹp. Nhưng .. đang Object.keystrở thành một toàn cầu trong ES6? Câu trả lời của bạn dường như giả định điều này, nhưng tôi không nhớ là đã thấy như đã lên lịch cho ES6.
FireFly

@FireFly Tôi không thể tìm thấy bất kỳ tài liệu nào, nhưng nó hoạt động tốt trong Firefox. Tôi chưa thử nghiệm nó trong Chrome / Opera / IE.
Bàn chải đánh răng

3

Groovy 77 82

thay đổi regex từ [^\w]+sang [^\d\p{L}]+để giải quyết vấn đề với dấu gạch dưới

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}

không có dòng đầu tiên, 82 ký tự

đầu ra:

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

nu_berkhông phải là chữ và số. Shouls này có 2 từ
Cruncher

Tại sao sử dụng nu_berthay vì number?
Kevin Fegan

Tôi đã bị đánh lừa bởi một số bài đăng khác;) bây giờ tôi đã xóa "_" khỏi đầu vào, nhưng đã sửa regex để xử lý nó
Kamil Mikolajchot

3

GNU awk + coreutils: 71 69

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

Mặc dù gawk asorthoạt động trên các mảng kết hợp, nhưng rõ ràng nó không bảo toàn các giá trị chỉ mục, đòi hỏi bên ngoàisort

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

Một giải pháp gawk lớn hơn một chút nhưng thuần túy sử dụng PROCINFOđể đặt thứ tự sắp xếp mặc định cho mảng kết hợp (dường như yêu cầu một gawk tương đối gần đây -> 4.x?)

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

Ôi trời ơi. Tôi không biết về PROCINFO. Như thể tôi cần một cái cớ để sử dụng awk trong cuộc sống của mình. Nguyền rủa bạn!
dmckee

@dmckee TBH Tôi không biết về PROCINFO cho đến khi tôi bắt đầu chọc ngoáy - Tôi tin chắc rằng phải có một cách để thực hiện sắp xếp một cách tự nhiên - thật đáng tiếc là các định danh quá dài;)
Steel thép

Trong những ngày xưa tồi tệ, đơn giản là không có cách nào. Điều này dẫn đến những điều như câu trả lời cũ này của tôi .
dmckee

-1. Gạch dưới _không nên được bao gồm trong một từ.
n̴̖̋h̷͉a̷̭̿h̸̡̅ẗ̵̨d̷̰ĥ̷̳

3

Javascript - 132 126 ký tự!

(Mã JS ngắn nhất)

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

Cải thiện regex và một số chỉnh sửa.


Bị đánh cắp

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 = "Ngày này không sáng bóng như thế nào"

=> [['là', 3],
['Làm thế nào', 1],
['sáng bóng', 1],
['này', 1],
['ngày', 1],
['isn', 1] ,
['t', 1]]


Cũ - 156 143 141 140 132 ký tự

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

Đã thử một lần đầu tiên tại golf. Phản hồi đánh giá cao.


2

EcmaScript 6, 115 100 87 (không có lời nhắc & cảnh báo)

Cảm ơn @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])

Với lời nhắc và cảnh báo (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]))

Chạy nó trong Firefox.


1
Bạn không cần var . Ngoài ra, bạn có thể di chuyển a={}bên trong prompt- prompt(a={}). Bạn cũng có thể thả Object.và thay đổi w=>a[w]=a[w]+1||1đểw=>a[w]=-~a[w]
eithed

Rất đẹp.
Đánh bại

Tương tự như câu trả lời của bàn chải đánh răng @ - việc chuyển khai báo atừ dấu nhắc sang regrec sẽ tiết kiệm thêm hai ký tự.
thúc vào

Thật đẹp và sạch sẽ. Làm tốt lắm!
Bàn chải đánh răng

-1. Gạch dưới _không nên được bao gồm trong một từ.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

2

Hồng ngọc 58 82 65

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

Chạy thử nghiệm:

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

Chỉnh sửa 58-> 80: Ok, tôi đã tắt. Tôi quên sắp xếp các từ theo sự xuất hiện. Ngoài ra, Array#uniqkhông phải là một điều tra viên, nhưng sử dụng một khối nhất định để so sánh các phần tử, vì vậy việc chuyển putssang nó không lọc ra các bản sao (không phải là nó nói rằng chúng ta nên).


1
Có lẽ split(/\W+/)thay vì scan(chưa được kiểm tra)?
Howard

@ Xin cảm ơn. \Wloại trừ _để phải sửa, nhưng nó vẫn lưu được 2 ký tự (sau đó tôi đã thêm 20 để sửa lỗi sắp xếp mà tôi đã bỏ qua).
daniero

Không nên được sắp xếp trongreverse (a=gets.split(/[_\W]+/)).uniq.map{|w|[w,a.count(w)]}.sort_by(&:last).reverse.map{|x|p x}
Eduard Florinescu

@EduardFlorinescu Nah. reverselà quá dài dòng;) Btw, thật không công bằng khi thay đổi câu hỏi.
daniero

Nếu bạn thấy trong mẫu đầu ra, nó chỉ được sắp xếp giảm xuống mà tôi quên chỉ định nó.
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"))

Bị thoái hóa:

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

Đầu ra khi được gọi từ 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 = ()

Cập nhật: Một số giải thích theo yêu cầu trong các ý kiến.

Sử dụng các hàm để tạo một mảng các ký tự không phải là chữ và số trong đầu vào để chuyển đến String.Split, sau đó sử dụng các hàm chuỗi để lọc ra các chuỗi trống, tạo ra số từ và in kết quả.

Một số thủ thuật đánh gôn: Thêm một chuỗi rỗng vào đối số hàm s để buộc suy luận kiểu của đối số là một chuỗi thay vì khai báo rõ ràng loại. Sử dụng Seq.where thay vì Seq.filter để lưu một vài ký tự (chúng là từ đồng nghĩa). Trộn đường ống chuyển tiếp và ứng dụng chức năng thông thường trong nỗ lực giảm thiểu các ký tự. Sử dụng cú pháp currying và (op) để xử lý <> ~ - và <|| toán tử như các hàm thông thường để tránh khai báo lambdas để lọc các chuỗi rỗng, sắp xếp theo số lượng giảm dần và in các bộ dữ liệu.


Bạn chắc chắn nên chèn một số loại giải thích; bằng cách đó chúng ta có thể hiểu mã của bạn.
Justin

Đã thêm một phiên bản khử và một số giải thích.
mattnewport

2

Python - 95 (hiện 87 nhờ @primo)

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

Đầu vào mẫu:

'This is a text and a number: 31'

Đầu ra mẫu:

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

Bất kỳ sự cải thiện đường sẽ được đánh giá cao


1
Giải pháp là tốt nhưng đầu ra không được sắp xếp.
Eduard Florinescu

Bạn có ý nghĩa gì khi sắp xếp? Cảm ơn đã bình luận.
Azwr

1
\wtrận đấu [a-zA-Z0-9_]. Toàn bộ regex của bạn có thể được thay thế bởi r'\w+'. Ngoài ra, xbiến không cần thiết, chỉ cần sử dụng raw_input()làm tham số thứ hai findall.
primo

Bằng cách sắp xếp, OP có nghĩa là các từ xuất hiện thường xuyên nhất cần được liệt kê đầu tiên. Ngoài ra, chương trình của bạn nên bao gồm một printtuyên bố (ví dụ print map(...), nếu không, nó không phải là một chương trình hoàn chỉnh.
Primo

Tôi không có thời gian để sắp xếp nó ngay bây giờ :( Tôi đang vội, cảm ơn vì những gợi ý và bình luận.
Azwr

2

JavaScript 160 144 (Đã chỉnh sửa: để đáp ứng yêu cầu)

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

Chưa hoàn thành:

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

Ghi nhật ký từng từ vào bảng điều khiển theo thứ tự, chuyển qua chuỗi sau:

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

Đầu ra:

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 

Tôi không có trái tim để sử dụng alert().


1
Sắp xếp nên theo số lượng. sự xuất hiện như vậy younên là đầu tiên.
Eduard Florinescu

@EduardFlorinescu Ngớ ngẩn với tôi ... Tôi sẽ sửa nó sau.
George Reith

Đã sửa lỗi @EduardFlorinescu
George Reith

-1. Gạch dưới _không nên được bao gồm trong một từ.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

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

2

k [71 ký tự]

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

Bất kỳ ký tự nào khác ngoại trừ ký tự chữ và số sẽ được coi là dấu phân cách.

thí dụ

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

thí dụ

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)

Chưa hoàn thành:

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)

Vòng lặp trên mỗi số lượng trận đấu có thể theo thứ tự giảm dần và xuất ra các từ có số lần xuất hiện đó. Chỉ để được kinh khủng.

Ghi chú: Thông báo sẽ giảm một số chiều dài. Nói đúng chữ và số nên được[^\W_]


2

Haskell (153 = 104 mã + 49 nhập)

Khá đơn giản, chức năng hoàn toàn bao gồm ... không cần tranh luận! Đây là golf đầu tiên của tôi, vì vậy đi dễ dàng, có thể? :)

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

Đầu ra:

*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

(50)

desc count each group" "vs ssr[;"[^0-9A-Za-z]";" "]
  • ssr thay thế không chữ và số
  • "" vs chia kết quả thành một danh sách ký hiệu
  • đếm từng nhóm đếm tạo ra một dict phù hợp với các yếu tố riêng biệt của danh sách với số lần xuất hiện
  • desc sắp xếp dict bằng cách giảm giá trị

chỉnh sửa: cố định vô tình khớp ascii 58-64 và 91-96


1
Tôi không có kiến ​​thức về qnhưng có phải là regex [0-z]ASCII không? Nếu có, nó cũng không bao gồm ký tự ASCII 58-64 phải không? Bởi vì đó là : ; < = > ? @.
jimbobmcgee

Bắt jimbob tuyệt vời, cảm ơn
nightTrevors

Không có gì; chỉ phát hiện vì tôi tìm thấy điều tương tự trong C #. Đáng buồn thay, giống với [A-z], phù hợp với ASCII 91-96, đó là `[\] ^
_`

ah phải bạn, bài học ascii nhỏ đẹp ngay đó!
nightTrevors

Tôi chỉ phát hiện ra [^_\W]+cho tôi, đó là "loại trừ các ký tự không phải từ và gạch dưới" , nếu cú ​​pháp của bạn hỗ trợ \Wlớp ...
jimbobmcgee

2

Pure Bash (không có chương trình bên ngoài), 164

Điều này dài hơn tôi mong đợi, nhưng tôi muốn xem liệu việc đếm và sắp xếp cần thiết (đúng hướng) có thể được thực hiện hoàn toàn với bashcác mảng (kết hợp và không liên kết):

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

Lưu dưới dạng tệp tập lệnh chmod +xvà chạy:

$ ./countoccur Đây là văn bản và số: 31.
a: 2
và 1
số 1
Văn bản 1
31: 1
là: 1
Đây: 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-"}'

Có công việc mà không có phần mở rộng 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

Thay vào đó, nếu in "Count: word", nó sẽ ngắn hơn một chút nhưng tôi muốn bắt chước đầu ra ví dụ đã cho ...



1

Python 2.X (108 - Ký tự)

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

Python 3.X (106 - Ký tự)

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- Bạn chỉ phân chia trên khoảng trắng.
daniero


1

Trăn 3 - 76

Yêu cầu tách trên các ký tự không chữ và số không may mở rộng mã thêm 19 ký tự. Đầu ra của sau đây được hiển thị chính xác. Nếu bạn không chắc chắn, hãy thêm một .most_common()sau .Counter(...).

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

Vào / ra

Cho đầu vào của This is a text and a number: 31.bạn nhận được đầu ra sau:

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

Tôi đã thử nó với các giá trị khác như

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

để đảm bảo, thứ tự đầu ra không phụ thuộc vào giá trị / hàm băm của khóa. Ví dụ này tạo ra:

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

Nhưng như tôi đã nói, print(i('collections').Counter(i('re').findall('\w+',input())).most_common())sẽ trả về kết quả dưới dạng một danh sách các bộ dữ liệu được sắp xếp chắc chắn .


Python 3 - 57 (nếu một không gian đủ để chia tách: P)

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

Nếu bạn giả sử chuỗi có trong một số biến, như một số câu trả lời khác, bạn có thể mất 6 ký tự bằng cách thay thế input ().
Phil H

@PhilH tốt. bạn đúng, nhưng tôi sẽ không bao giờ đọc được điều đó trong số các yêu cầu. chắc chắn rằng "chuỗi cho JavaScript" có thể gợi ý nó, nhưng tôi không thể, với lương tâm rõ ràng, diễn giải một biến chuỗi là "đầu vào" hợp lệ. Nhưng bạn đúng. điều đó sẽ rút ngắn nó hơn nữa. : P
Dave J

-1. Gạch dưới _không nên được bao gồm trong một từ.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

Vâng, điều này phụ thuộc vào định nghĩa của alpha-số. Trong Python, "\ w" được xác định để chấp nhận ký tự chữ và số. Bạn có thể đúng nhưng với cách giải thích các quy tắc này, giải pháp của tôi vẫn đúng. :)
Dave J
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.