นับจำนวนคำในข้อความและแสดง


26

รหัสควรรับข้อความ (ไม่บังคับอาจเป็นไฟล์อะไรก็ได้ stdin, string สำหรับ JavaScript และอื่น ๆ ):

This is a text and a number: 31.

ผลลัพธ์ควรมีคำที่มีจำนวนการเกิดขึ้นเรียงตามจำนวนที่เกิดขึ้นตามลำดับจากมากไปน้อย:

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

โปรดสังเกตว่า 31 เป็นคำดังนั้นคำใด ๆ ที่เป็นตัวอักษรและตัวเลขตัวเลขจะไม่ทำหน้าที่เป็นตัวคั่นดังนั้นตัวอย่างจึง0xAFมีคุณสมบัติเป็นคำ ตัวคั่นจะเป็นอะไรก็ได้ที่ไม่ใช่ตัวเลขรวมถึง.(จุด) และ-(ยัติภังค์) ดังนั้นi.e.หรือpick-me-upจะให้ผลลัพธ์เป็น 2 ตามลำดับ 3 คำ ควรจะเป็นกรณีที่มีความสำคัญThisและthisจะเป็นสองคำที่แตกต่างกัน 'ก็จะแยกเพื่อให้wouldnและtจะมี 2 wouldn'tคำที่แตกต่างจาก

เขียนรหัสที่สั้นที่สุดในภาษาที่คุณเลือก

คำตอบที่ถูกต้องสั้นที่สุด:


5
กรณีมีความสำคัญ (เช่นThisเดียวกับthisและtHIs) หรือไม่?
Gareth

หากมีสิ่งใดที่ไม่ใช่ตัวอักษรและตัวเลขนับเป็นตัวคั่นwouldn't2 คำคือ ( wouldnและt)?
Gareth

@Gareth ควรจะเป็นกรณีที่มีความสำคัญThisและthisจะเป็นจริงคำสองคำที่แตกต่างกันเหมือนกันและwouldn t
Eduard Florinescu

ถ้าไม่ใช่คำ 2 คำมันควรจะเป็น "Will" และ "nt" หรือไม่เพราะย่อมาจากคำว่าจะไม่ใช้
Teun Pronk

@TeunPronk ฉันพยายามทำให้มันง่ายการวางกฎเล็กน้อยจะส่งเสริมข้อยกเว้นให้เป็นไปตามหลักไวยากรณ์และมีข้อยกเว้นมากมายออกมาที่นั่น Ex ในภาษาอังกฤษi.e.เป็นคำ แต่ถ้าเราปล่อยให้จุดทั้งหมดเป็นจุดที่ ในตอนท้ายของวลีที่จะต้องดำเนินการเช่นเดียวกันกับคำพูดหรือคำพูดเดียว ฯลฯ
เอดูอาร์ Florinescu

คำตอบ:


27

grep และ coreutils  44  42

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

ทดสอบ:

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

ผลลัพธ์ใน:

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

ปรับปรุง

  • ใช้ตัวเลือกที่ไม่คำนึงถึงตัวพิมพ์เล็กและตัวย่อ regex ขอบคุณโทมัส

2
นี้เป็นเกือบจะตอบสนอง McEllroy เพื่อ Knuth หนังสือLiterate การเขียนโปรแกรม ความแตกต่างเพียงอย่างเดียวคือสิ่งนี้ไม่รวมท่อเข้าไปheadในตอนท้าย
AJMansfield

นี่เป็นความคิดแรกของฉันด้วย
Rob

1
จะไม่ได้ '\ w +' เช่นกันใช่ไหม
Sylwester

1
41 ตัวอักษร :grep -io \[A-Z0-9]*|sort|uniq -c|sort -nr
โทมัส

1
@Tomas: เพิ่มสิ่งนี้ในคำตอบขอบคุณ ฉันทิ้งการป้องกันไว้สำหรับเครื่องหมายดอกจันเพราะมันกำลังขยายชื่อไฟล์ในเชลล์บางตัว
Thor

18

Java 8: 289

ซึ่งค่อนข้างดีเนื่องจากภาษาจาวาเป็นภาษาที่ไม่เล่นกอล์ฟมาก

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

เรียกใช้จากบรรทัดคำสั่ง:

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

regex ผิดสำหรับการแยก มันควรจะเป็น"[^\\W_]"
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ String.split(String regex)วิธีใช้รูปแบบที่ตรงกับตัวคั่นเพื่อแยก ดังนั้นสำหรับตัวอย่างเช่นจะให้ผลผลิตอาร์เรย์"aababba".split("b") {"aa", "a", "", "a"}regex ของฉัน[^\\w\\d]หมายถึง 'ตัวละครไม่ว่าจะเป็นตัวอักษรคำหรือตัวละครหลัก' [^\\W_]แทน 'อักขระที่ไม่ใช่ขีดล่างหรืออยู่ในคลาสที่ไม่ใช่คำ - อักขระ' และจะจับคู่อักขระคำใด ๆ ยกเว้นขีดล่าง
AJMansfield

ขออภัยความคิดเห็นก่อนหน้าของฉันไม่ถูกต้อง \wรวมถึง\dจึง\dซ้ำซ้อน \wรวมถึงขีดล่างซึ่งควรพิจารณาเป็นตัวคั่นตามคำถาม ดังนั้น regex "[\\W_]+"ที่ถูกต้องสำหรับการแยกควรจะเป็น
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ โอเคขอบคุณ; ฉันแก้ไขปัญหาแล้ว
AJMansfield

17

APL (57)

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

เช่น

      ⎕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

คำอธิบาย:

  • ⎕D,⎕A,⎕UCS 96+⍳26: ตัวเลขตัวอักษรตัวพิมพ์ใหญ่ตัวอักษรตัวเล็ก
  • (I←⍞)∊: อ่านอินพุต, เก็บในI, ดูว่าอันไหนเป็นตัวอักษรและตัวเลข
  • Z←I⊂⍨: แยกเป็นIกลุ่มของตัวอักษรและตัวเลขเก็บในZ
  • +⌿∘.≡⍨Z: สำหรับแต่ละองค์ประกอบในZดูความถี่ที่มันเกิดขึ้น
  • Z,⍪: จับคู่แต่ละองค์ประกอบเป็นZคู่กับจำนวนครั้งที่มันเกิดขึ้น
  • G←⊃∪↓: เลือกเฉพาะคู่ที่ไม่ซ้ำกันเก็บไว้ใน G
  • ⍒,1↓⍉G: รับดัชนีเรียงลำดับสำหรับการเกิดขึ้น
  • G[... ;]: จัดลำดับบรรทัดใหม่Gตามดัชนีที่กำหนด

6
สิ่งที่ ... และ ... ฉ .....
Ozh

6
นี่คือเหตุผลที่ฉันฝันร้าย
Thebluefish

3
@Thebluefish: APL ได้รับการออกแบบมาจากสัญกรณ์โดยมีความตั้งใจว่าคณิตศาสตร์จะทำให้คุณคิดได้ชัดเจน เช่นเดียวกับคณิตศาสตร์เมื่อคุณเห็นสัญกรณ์นั้นเป็นครั้งแรกคุณมักจะคิดว่ามันไม่ชัดเจนเลย แต่ภาษาดูเหมือนจะเริ่มต้นที่ซับซ้อนเสมอ มันจะง่ายขึ้นถ้ามันไม่ได้อยู่ในบรรทัดเดียว ...
ฟิลเอช

ไม่ว่าคุณจะเกิดอะไรขึ้นใน APL ฉันเห็นเพียงขยะยูนิโค้ดลูกศรชี้ไปในทิศทางและต้นสนคว่ำ นั่นเลวร้ายยิ่งกว่า J
bebe

อาจจะสั้นลงด้วย⎕s( help.dyalog.com/latest/Content/Language/System%20Functions/... ) และผู้ประกอบการใหม่ที่สำคัญ ( 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

(ผ่าน LINQPad ในโหมด "คำสั่ง C #" ไม่รวมสตริงอินพุต)

รุ่น 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

ผล:

Results

รุ่น 2: 114c

( [\w]รวมถึงการ_ที่ไม่ถูกต้อง !; [A-z]รวมถึง[ \ ] ^ _ `; ปักหลักบน[^_\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

ผลลัพธ์: (เป็นเวอร์ชัน 1)


อย่างไรก็ตามสำหรับรุ่น 2 รุ่นที่คุณไม่ได้อัปโหลดนั้นไม่ตรงกับรุ่นที่คุณเล่นกอล์ฟ และเนื่องจากคุณกำลังใช้สตริงตัวอักษรคุณสามารถเขียน@"[^_\W]"
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳ - แก้ไขคำผิดและลบส่วนเสริมพิเศษ `` เพื่อการประหยัดแบบ 1 ถ่าน - ขอบคุณ !!
jimbobmcgee

7

R, 58 ตัวอักษร

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

การใช้งาน:

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 

นี่คือสั้น (49 sort(table(gsub("[[:punct:]]","",scan(,""))),d=T)ตัวอักษร) wouldn'tแต่น่าเสียดายที่การแก้ปัญหาทั้งสองไม่สามารถทำงานได้อย่างถูกต้องสำหรับ
djhurio

6

perl6: 49 ตัวอักษร

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

ป้อนอินพุตสำหรับการจับคู่สิ่งต่าง ๆ\w+ใส่รายการคำที่เป็นผลลัพธ์ใน a Bagขอคู่ของพวกเขาและเรียงลำดับตามค่าลบ (คน*เป็นสิ่งที่ดาวก็ไม่คูณที่นี่)

เอาท์พุท:

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

3
Perl 6 กลัวฉัน
primo

1
ทุกครั้งที่ฉันคิดถึงคุณสมบัติภาษาที่ยอดเยี่ยมฉันจะมองหามันและมันก็อยู่ใน Perl6 ที่ไหนสักแห่ง นั่นเป็นเหตุผลว่าทำไมจึงใช้เวลานาน ...
Phil H

คุณสามารถตัดแต่งอักขระได้ 6 ตัวโดยใช้.wordsแทน.comb(/\w+/):)
Mouq

@Mouq: น่าเสียดายที่.wordsไม่ได้ตัด:หรือ.จากอินพุตตามที่ต้องการ :(
Ayiko

-1 _ไม่ควรรวมอยู่ในคำใต้คำชี้แจงปัญหา
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)

ตอนนี้ทำงานกับ 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

สิ่งนี้ไม่ทำงานเมื่อมีการขึ้นบรรทัดใหม่หรือมากกว่าหนึ่งช่องว่างต่อเนื่องกันในข้อความ
klingt.net

@ klingt.net แก้ไขแล้ว
daniero

6

PHP - 84 ไบต์

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

อินพุตได้รับการยอมรับเป็นอาร์กิวเมนต์บรรทัดคำสั่งเช่น:

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

เอาต์พุตสำหรับสตริงตัวอย่าง:

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

1
มันบอกว่าการป้อนข้อมูลคือสิ่งที่คุณต้องการ เพื่อให้คุณสามารถรับมันเป็นพารามิเตอร์บรรทัดคำสั่งโดยใช้$argv[1]
Einacio

@Einacio โทรดี
primo

-1 _ไม่ควรใส่เครื่องหมายขีดล่างในคำ
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

แก้ไขแล้ว @ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
primo

5

PowerShell (40)

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

$ s เป็นตัวแปรที่มีสตริงการป้อนข้อมูล


2
[\W]ไม่ดีพอ - มันจับคู่ช่องว่างในการทดสอบของฉัน และจะไม่ได้รับคำสั่งจากจำนวนมากไปหาน้อย ...
jimbobmcgee

$s -split"[\W]"|group -ca|where{$_.Name -ne ""}|sort{-$_.Count}ทำให้คุณใกล้ชิดยิ่งขึ้น (ด้วยค่าใช้จ่ายแน่นอน)
jimbobmcgee

อุ๊ปส์ฉันพลาดส่วนการจัดเรียง จะแก้ไขคำตอบของฉันในไม่ช้า
microbian

อีกทางเลือกหนึ่ง:$s -split"\W+"|group -ca |sort count -des
Nacimota

4
-split"\W+"กำลังจับคู่สตริงว่างระหว่างสตริงสุดท้าย.และสุดท้าย; การ\W+แข่งขัน_ที่ไม่อนุญาตให้
ทำได้เช่นเดียวกัน

4

Perl 69

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

เพิ่มคำแนะนำจาก @primo และ @protist


1
แล้วการเรียงลำดับล่ะ?
daniero

@daniero จุดที่ยอดเยี่ยม! ตอนนี้มันแปลก!
Dom Hastings

1
ฉันคิดว่ามันเป็นเรื่องที่สั้นที่สุดเท่าที่จะทำได้ หากคุณไม่ทราบคำเตือนเลิกใช้ไม่มีพื้นที่ต้องระหว่างและge forนอกจากนี้ผู้ประกอบการจะถูกแทนที่ด้วย<=> -
primo

2
@primo Ahhh -แทนที่จะ<=>เป็นอัจฉริยะไม่แน่ใจว่าเป็นเคล็ดลับในการเล่นกอล์ฟสำหรับหัวข้อ Perl ฉันจะอัปเดตในภายหลังขอบคุณ!
Dom Hastings

1
สวัสดี @protist \wรวมถึงตัวเลขด้วย ( perl -e 'print for"a 1 2 3 4 b"=~/\w/g'พิมพ์a1234b) แต่กลไกของคุณสำหรับการวนซ้ำคำจะบันทึกอักขระอื่นดังนั้นฉันจะอัปเดต ขอขอบคุณ!
Dom Hastings

4

PowerShell: 57 55 53 62 57

(ไม่รวมสตริงอินพุต)

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

ผลตอบแทน:

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}

(พร้อม props ถึง @microbian สำหรับกลุ่ม -ca)


3

EcmaScript 6

รุ่น 1 (108 ตัวอักษร)

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

รุ่น 2 (102 ตัวอักษร)

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

เวอร์ชัน 3 (105 ตัวอักษร)

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

รุ่น 4 (94 ตัวอักษร)

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

รุ่น 5 (ไม่มีการแจ้งเตือน; 87 ตัวอักษร)

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

รุ่น 6 (100 ตัวอักษร)

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

เอาท์พุท:

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

คุณสามารถเปลี่ยน_[a]และ_[b]ไปและ_.a _.bการเปลี่ยน/\w+/g,_={}ไปเป็น_=/\w+/gจะให้ผลลัพธ์เดียวกัน
eithed

@eithedog ขอขอบคุณ! แต่ผมไม่สามารถเปลี่ยน_[a]ให้เป็น_.aเพราะมันพยายามเข้าถึงทรัพย์สิน"a"ของไม่ได้ทรัพย์สิน_ a
แปรงสีฟัน

อ่าถูกต้องคำสั่งจะไม่ถูกเก็บไว้ ดำเนินการ :)
eithed

โอ้ฉันไม่ได้สังเกตคำตอบของคุณ .. ดี แต่ .. กำลังObject.keysกลายเป็น ES6 ทั่วโลก? คำตอบของคุณดูเหมือนจะถือว่าเป็นสิ่งนี้ แต่ฉันจำไม่ได้ว่าสิ่งนั้นตามกำหนดเวลาสำหรับ ES6
FireFly

@FireFly ฉันไม่พบเอกสารใด ๆ แต่ใช้งานได้ดีใน Firefox ฉันยังไม่ได้ทดสอบใน Chrome / Opera / IE
แปรงสีฟัน

3

Groovy 77 82

เปลี่ยน regex จาก[^\w]+เป็น[^\d\p{L}]+เพื่อแก้ปัญหาด้วยการขีดเส้นใต้

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}

ไม่มีบรรทัดแรก, 82 ตัวอักษร

เอาท์พุท:

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

nu_berไม่ใช่ตัวอักษรและตัวเลข shouls นี้มี 2 คำ
Cruncher

ทำไมต้องใช้nu_berแทนnumber?
Kevin Fegan

ฉันถูกทำให้เข้าใจผิดโดยโพสต์อื่น ๆ ;) ตอนนี้ฉันลบ "_" ออกจากอินพุต แต่แก้ไข regex เพื่อจัดการมัน
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

แม้ว่าจะgawk asortใช้ได้กับอาเรย์แบบเชื่อมโยง แต่ก็ไม่ได้เก็บค่าดัชนีไว้sort

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

โซลูชัน gawk ที่ใหญ่กว่า แต่บริสุทธิ์ใช้PROCINFOสำหรับตั้งค่าการเรียงลำดับเริ่มต้นสำหรับอาร์เรย์ที่เชื่อมโยง (ดูเหมือนจะต้องการ gawk ที่ค่อนข้างล่าสุด -> 4.x?)

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

Oooooh ฉันไม่รู้เกี่ยวกับ PROCINFO ราวกับว่าฉันต้องการข้อแก้ตัวอื่นที่จะใช้ awk ในชีวิตของฉัน สาปแช่งคุณ!
dmckee

@dmckee TBH ผมไม่ทราบว่าเกี่ยวกับ PROCINFO จนผมเริ่ม poking รอบ - ฉันเชื่อว่ามีมีจะเป็นวิธีการที่จะทำเรียงลำดับโดยกำเนิด - การเพียงแค่สงสารตัวระบุจึงยาว;)
steeldriver

ในวันเก่าที่เลวร้ายนั้นก็ไม่มีทาง ซึ่งนำไปสู่สิ่งที่ต้องการคำตอบเก่าของฉัน
dmckee

-1 _ไม่ควรใส่เครื่องหมายขีดล่างในคำ
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

3

Javascript - 132 126 ตัวอักษร!

(รหัส JS สั้นที่สุด)

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

ปรับปรุง regex และการแก้ไขบางอย่าง


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 = "วันนี้มันวาวแค่ไหนกันไม่ได้"

=> [['คือ', 3],
['How', 1],
['Shiny', 1],
['this', 1],
['day', 1],
['isn', 1] ,
['t', 1]]


เก่า - 156 143 141 140 132 ตัวอักษร

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

ลองเล่นกอล์ฟเป็นครั้งแรก ข้อเสนอแนะชื่นชม


2

EcmaScript 6, 115 100 87 (โดยไม่ต้องแจ้งเตือน & พร้อม)

ขอบคุณ @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])

ด้วยพรอมต์และการแจ้งเตือน (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]))

เรียกใช้ใน Firefox


1
var คุณไม่จำเป็นต้อง นอกจากนี้คุณยังสามารถย้ายa={}ภายใน-prompt prompt(a={})นอกจากนี้คุณยังสามารถวางObject.และการเปลี่ยนแปลงw=>a[w]=a[w]+1||1ไปw=>a[w]=-~a[w]
eithed

ดีมาก. เอาชนะ Python ที่ใช้งานได้ในตอนนี้ :)
teh_senaus

เช่นเดียวกับคำตอบของ @ toothbrush การย้ายการประกาศaจากพรอมต์ไปยัง regexp จะสำรองตัวอักษรสองตัวอีก
eithed

มันสวยและสะอาด เยี่ยมมาก!
แปรงสีฟัน

-1 _ไม่ควรใส่เครื่องหมายขีดล่างในคำ
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

2

ทับทิม58 82 65

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

ทดสอบการทำงาน:

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

แก้ไข 58-> 80: โอเคฉันถูกออกไปแล้ว ฉันลืมเรียงลำดับคำตามเหตุการณ์ที่เกิดขึ้น นอกจากนี้Array#uniqไม่ได้เป็นตัวแจงนับ แต่ใช้บล็อกที่กำหนดเพื่อเปรียบเทียบองค์ประกอบดังนั้นการส่งผ่านputsไปจึงไม่กรองการทำซ้ำ (ไม่ใช่บอกว่าเราควร)


1
อาจจะsplit(/\W+/)แทนที่จะเป็นscan(ยังไม่ทดลอง)?
Howard

@Howard ขอบคุณ \Wไม่รวม_เพื่อให้ได้รับการแก้ไข แต่ก็ยังบันทึก 2 ตัวอักษร (จากนั้นฉันเพิ่ม 20 เพื่อแก้ไขการเรียงลำดับที่ฉันถูกทอดทิ้ง)
daniero

ไม่ควรเรียงลำดับ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เป็นวิธี verbose เกินไป;) Btw มันไม่ยุติธรรมเปลี่ยนคำถาม
daniero

หากคุณเห็นในตัวอย่างผลลัพธ์มันจะเรียงลำดับลงมาเท่านั้นที่ฉันลืมที่จะระบุ
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"))

เอาต์พุตเมื่อถูกเรียกจาก 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 = ()

ปรับปรุง:คำอธิบายบางอย่างตามที่ร้องขอในความคิดเห็น

ใช้ฟังก์ชัน set เพื่อสร้างอาร์เรย์ของอักขระที่ไม่ใช่ตัวอักษรและตัวเลขในอินพุตเพื่อส่งไปยัง String.Split จากนั้นใช้ฟังก์ชันลำดับเพื่อกรองสตริงว่างสร้างคำนับและพิมพ์ผลลัพธ์

เทคนิคการตีกอล์ฟบางรายการ: เพิ่มสตริงว่างลงในอาร์กิวเมนต์ของฟังก์ชันเพื่อบังคับอนุมานประเภทของอาร์กิวเมนต์เป็นสตริงแทนที่จะประกาศประเภทอย่างชัดเจน ใช้ Seq.where แทน Seq.filter เพื่อบันทึกอักขระสองสามตัว (เป็นคำพ้องความหมาย) ผสมไปข้างหน้าไปป์และแอปพลิเคชั่นฟังก์ชั่นสามัญในความพยายามที่จะลดตัวอักษร ใช้ currying และ (op) ไวยากรณ์ในการปฏิบัติ <> ~ - และ <|| ผู้ประกอบการเป็นฟังก์ชั่นปกติเพื่อหลีกเลี่ยงการประกาศ lambdas เพื่อกรองสตริงว่างเรียงลำดับจากมากไปน้อยนับและพิมพ์สิ่งอันดับ


คุณควรแทรกคำอธิบายบางอย่างแน่นอน; ด้วยวิธีนี้เราสามารถเข้าใจรหัสของคุณได้
Justin

เพิ่มเวอร์ชั่น degolfed และคำอธิบายบางอย่าง
mattnewport

2

Python - 95 (ตอนนี้ 87 ต้องขอบคุณ @primo)

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

ตัวอย่างอินพุต:

'This is a text and a number: 31'

ตัวอย่างผลลัพธ์:

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

การปรับปรุงความแออัดใด ๆ จะได้รับการชื่นชม


1
การแก้ปัญหาเป็นสิ่งที่ดี แต่ผลลัพธ์ไม่ได้เรียง
Eduard Florinescu

คุณหมายถึงอะไรเรียงตาม? ขอบคุณสำหรับความคิดเห็น
Azwr

1
\w[a-zA-Z0-9_]ไม้ขีด regex r'\w+'ทั้งหมดของคุณจะถูกแทนที่ด้วย นอกจากนี้xตัวแปรไม่จำเป็นต้องใช้เพียงเป็นพารามิเตอร์ที่สองไปraw_input() findall
primo

เมื่อเรียงลำดับแล้ว OP หมายถึงคำที่ปรากฏส่วนใหญ่มักจะต้องมีการระบุไว้ก่อน นอกจากนี้โปรแกรมของคุณควรมีprintคำสั่ง (เช่นprint map(...) มิฉะนั้นมันไม่ใช่โปรแกรมที่สมบูรณ์
primo

ฉันไม่มีเวลาที่จะจัดเรียงตอนนี้ :( ฉันกำลังรีบขอบคุณสำหรับคำแนะนำและความคิดเห็น
Azwr

2

JavaScript 160 144 (แก้ไข: เพื่อตอบสนองความต้องการ)

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

บันทึกคำแต่ละคำในคอนโซลตามลำดับผ่านสตริงต่อไปนี้:

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

ขาออก:

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 

alert()ฉันไม่ได้มีหัวใจที่จะใช้


1
การเรียงลำดับควรเป็นตัวเลข เกิดขึ้นดังนั้นyouควรจะเป็นครั้งแรก
Eduard Florinescu

@EduardFlorinescu Silly ฉัน ... ฉันจะแก้ไขในภายหลัง
George Reith

@EduardFlorinescu แก้ไขแล้ว
George Reith

-1 _ไม่ควรใส่เครื่องหมายขีดล่างในคำ
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

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

2

k [71 ตัวอักษร]

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

อักขระอื่นใดยกเว้นตัวอักษรและตัวเลขจะถือว่าเป็นตัวคั่น

ตัวอย่าง

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

ตัวอย่าง

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)

วนซ้ำทุก ๆ การจับคู่ที่เป็นไปได้ตามลำดับจากมากไปน้อย เพียงเพื่อจะน่ากลัว

หมายเหตุ: การแจ้งเตือนจะลดความยาวลงได้บ้าง ตัวอักษรและตัวเลขที่พูดอย่างเคร่งครัดควรเป็น[^\W_]


2

Haskell (153 = 104 code + 49 import)

ฟังก์ชั่นที่ค่อนข้างตรงไปตรงมาสวยมาก ... ไม่มีข้อโต้แย้ง! นี่คือสนามกอล์ฟครั้งแรกของฉันดังนั้นไปง่าย ๆ อาจจะ? :)

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

เอาท์พุท:

*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 แทนที่ไม่ใช่ตัวอักษรและตัวเลข
  • "" vs แยกผลลัพธ์ออกเป็นรายการสัญลักษณ์
  • นับแต่ละกลุ่มนับสร้าง dict จับคู่องค์ประกอบที่แตกต่างของรายการที่มีจำนวนเกิดขึ้น
  • desc เรียงลำดับ dict ตามค่าจากมากไปน้อย

แก้ไข: แก้ไขการจับคู่โดยบังเอิญโดยบังเอิญ 58-64 และ 91-96


1
ฉันไม่รู้qแต่ใช้ regex [0-z]ASCII หรือไม่ ถ้าเป็นเช่นนั้นจะไม่รวมตัวอักษร ASCII 58-64 ด้วยหรือไม่ : ; < = > ? @เพราะผู้ที่มี
jimbobmcgee

จับ jimbob ยอดเยี่ยมขอบคุณ
nightTrevors

ไม่เป็นไร พบเพียงเพราะฉันพบเหมือนกันใน C # น่าเศร้าเช่นเดียวกับ[A-z]ซึ่งตรงกับ ASCII 91-96 ซึ่งเป็น `[\] ^
_`

ใช่แล้วคุณคือบทเรียนบทเรียน ascii ที่ดีที่นั่น!
nightTrevors

ฉันเพิ่งค้นพบ[^_\W]+ของฉันซึ่งควรจะ"ไม่รวมตัวอักษรที่ไม่ใช่คำและขีดเส้นใต้"ถ้าไวยากรณ์ของคุณรองรับ\Wชั้น ...
jimbobmcgee

2

Pure Bash (ไม่มีโปรแกรมภายนอก), 164

สิ่งนี้นานกว่าที่ฉันคาดหวัง แต่ฉันต้องการดูว่าการนับและการเรียงลำดับที่จำเป็น (ในทิศทางที่ถูกต้อง) สามารถทำได้อย่างหมดจดด้วยbashอาร์เรย์ (เชื่อมโยงและไม่เชื่อมโยง):

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

บันทึกเป็นไฟล์สคริปต์ chmod +xและเรียกใช้:

$ ./countoccur นี่คือข้อความและตัวเลข: 31
A: 2
และ: 1
จำนวน: 1
ข้อความ: 1
31: 1
คือ 1
นี้: 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-"}'

ทำงานได้โดยไม่ต้องมีส่วนขยายที่น่ารังเกียจ:

$ 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

หากพิมพ์ "count: word" แทนมันจะสั้นลงเล็กน้อย แต่ฉันต้องการเลียนแบบผลลัพธ์ตัวอย่างที่กำหนด ...



1

Python 2.X (108 - ตัวละคร)

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

Python 3.X (106 - ตัวละคร)

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- คุณแยกช่องว่างเท่านั้น
daniero


1

Python 3 - 76

ความต้องการในการแยกตัวอักษรที่ไม่ใช่ตัวอักษรและตัวเลขมีการขยายรหัส 19 ตัวอักษร ผลลัพธ์ของสิ่งต่อไปนี้แสดงอย่างถูกต้อง หากคุณไม่แน่ใจว่าเพิ่มหลังจากที่.most_common().Counter(...)

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

In / เอาท์พุท

รับอินพุตของThis is a text and a number: 31.คุณรับเอาต์พุตต่อไปนี้:

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

ฉันลองกับค่าอื่น ๆ เช่น

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

เพื่อให้มั่นใจว่าคำสั่งส่งออกไม่ได้ขึ้นอยู่กับมูลค่า / แฮชของคีย์ ตัวอย่างนี้ผลิต:

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

แต่ที่ผมบอกว่าprint(i('collections').Counter(i('re').findall('\w+',input())).most_common())จะกลับมาผลเป็นมั่นเหมาะรายการสั่งซื้อของ tuples


Python 3 - 57 (หากมีพื้นที่เพียงพอสำหรับการแยก: P)

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

หากคุณคิดว่าสตริงอยู่ในตัวแปร s เช่นเดียวกับคำตอบอื่น ๆ คุณอาจสูญเสียอักขระ 6 ตัวโดยการแทนที่อินพุต ()
Phil H

@PhilH ดี คุณพูดถูก แต่ฉันจะไม่มีวันอ่านข้อกำหนดนั้น ตรวจสอบให้แน่ใจว่า "สตริงสำหรับ JavaScript" - ส่วนอาจแนะนำ แต่ฉันไม่สามารถแปลความหมายสตริงตัวแปรเป็น "อินพุต" ที่ถูกต้องได้ แต่คุณพูดถูก ที่จะย่อให้สั้นยิ่งขึ้น : P
Dave J

-1 _ไม่ควรใส่เครื่องหมายขีดล่างในคำ
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

นี่ขึ้นอยู่กับนิยามของตัวเลขและตัวอักษร ใน Python มีการกำหนด "\ w" เพื่อยอมรับตัวอักษรและตัวเลข คุณอาจจะถูกต้อง แต่ด้วยการตีความกฎชนิดนี้ทางออกของฉันก็ยังคงถูก :)
Dave J
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.