Policz słowa w tekście i wyświetl je

26

Kod powinien pobierać tekst (nieobowiązkowe może być dowolny plik, standardowe wejście, ciąg znaków dla JavaScript itp.):

This is a text and a number: 31.

Dane wyjściowe powinny zawierać słowa z ich liczbą wystąpień, posortowane według liczby wystąpień w kolejności malejącej:

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

Zauważ, że 31 jest słowem, więc słowo jest dowolną alfanumeryczną, liczba nie działa jako separator, więc na przykład 0xAFkwalifikuje się jako słowo. Separatory będą to wszystko, co nie jest alfanumeryczne, w tym .(kropka) i -(łącznik) w ten sposób i.e.lub pick-me-updadzą 2 lub 3 słowa. Powinna być wielkość liter, Thisi thisbędzie dwa różne słowa, 'byłoby również separator tak wouldni tbędą 2 różne słowa z wouldn't.

Napisz najkrótszy kod w wybranym języku.

Najkrótsza jak dotąd poprawna odpowiedź:

Eduard Florinescu
źródło
5
Czy sprawa ma znaczenie (tzn. Czy jest Thistaka sama jak thisi tHIs)?
Gareth
Jeśli coś niealfanumerycznego liczy się jako separator, to czy wouldn't2 słowa ( wouldni t)?
Gareth
@Gareth Powinny być rozróżniane małe Thisi wielkie litery, i thisrzeczywiście będą to dwa różne słowa, to samo wouldni t.
Eduard Florinescu
Jeśli nie byłyby to dwa słowa, czy nie powinny to być słowa „nie” i „nt”, ponieważ są skrótem od słowa „nie”, czy też jest to o wiele gramatyczniejsze nazistowskie podejście?
Teun Pronk
@TeunPronk Staram się to uprościć, wprowadzenie kilku reguł zachęci do wyjątków w zakresie gramatyki i istnieje wiele wyjątków. Np. W języku angielskim i.e.to słowo, ale jeśli pozwolimy kropce wszystkie kropki na koniec fraz będzie pobierany, tak samo jak cytaty lub pojedyncze cytaty itp.
Eduard Florinescu

Odpowiedzi:

27

grep i 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

Prowadzi do:

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

Aktualizacja

  • Użyj opcji bez rozróżniania wielkości liter i krótszego wyrażenia regularnego. Dzięki Tomas.
Thor
źródło
2
Jest to niemal dokładnie odpowiedź McEllroya na książkę Knutta Literate Programming . Jedyną różnicą jest to, że nie obejmuje ona rury headna końcu.
AJMansfield
To była moja pierwsza myśl.
Rob
1
Czy „w +” też nie działałoby?
Sylwester
1
41 znaków :grep -io \[A-Z0-9]*|sort|uniq -c|sort -nr
Tomas
1
@Tomas: Dodałem to do odpowiedzi, dzięki. Zostawiłem ochronę dla gwiazdki, ponieważ rozszerzała nazwy plików w niektórych powłokach.
Thor
18

Java 8: 289

Co jest całkiem dobre, ponieważ java jest językiem bardzo nie golfowym.

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

Nie golfowany:

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

Uruchom z wiersza poleceń:

java -jar wordCounter.jar This is a text and a number: 31.
AJMansfield
źródło
Niepoprawne wyrażenie regularne dla podziału. Powinno być"[^\\W_]"
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨d̷̰̀ĥ̷̳, String.split(String regex)metoda przyjmuje wzorzec pasujący do separatora, na którym ma się dzielić. Na przykład "aababba".split("b")dałoby tablicę {"aa", "a", "", "a"}. Moje wyrażenie regularne [^\\w\\d]oznacza „znak ani w klasie znakowej, ani cyfrowej”. [^\\W_]jest natomiast „znakiem, który nie jest ani znakiem podkreślenia, ani nie należy do klasy znaków niebędących wyrazami” i pasowałby do dowolnego znaku słownego oprócz znaku podkreślenia.
AJMansfield,
Przepraszamy, mój poprzedni komentarz był niepoprawny. \wobejmuje \d, więc \djest zbędny. \wzawiera podkreślnik, który zgodnie z pytaniem należy uznać za separator. Tak więc poprawne wyrażenie regularne dla dzielenia powinno być "[\\W_]+".
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨dd
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨d̷̰̀ĥ̷̳ ok, dzięki; Naprawiłem problem.
AJMansfield
17

APL (57)

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

na przykład

      ⎕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

Wyjaśnienie:

  • ⎕D,⎕A,⎕UCS 96+⍳26: cyfry, wielkie litery, małe litery
  • (I←⍞)∊: wczytaj dane wejściowe, zapisz w I, zobacz, które są alfanumeryczne
  • Z←I⊂⍨: podzielone Ina grupy znaków alfanumerycznych, zapisz wZ
  • +⌿∘.≡⍨Z: dla każdego elementu w Zzobacz, jak często występuje
  • Z,⍪: dopasuj każdy element Zparami z tym, ile razy występuje
  • G←⊃∪↓: wybierz tylko unikalne pary, zapisz w G
  • ⍒,1↓⍉G: uzyskaj posortowane wskaźniki dla zdarzeń
  • G[... ;]: zmiana kolejności wierszy Gwedług podanych indeksów
marinus
źródło
6
co ... the ... f .....
Ozh
6
Właśnie dlatego mam koszmary.
Thebluefish
3
@Thebluefish: APL został zaprojektowany na podstawie zapisu, z zamiarem, że podobnie jak matematyka, zwięzły zapis pozwala swobodnie myśleć. Znowu jak matematyka, kiedy po raz pierwszy widzisz tę notację, masz tendencję do myślenia, że ​​wcale nie jest to jasne, ale języki zawsze wydają się skomplikowane. Byłoby łatwiej, gdyby nie wszystko było w jednym wierszu ...
Phil H
cokolwiek wymyślisz w APL, widzę tylko śmieci unicode, strzały skierowane w kierunkach i odwróconą sosnę. to gorsze niż J
bebe
Może być krótszy z ⎕s( help.dyalog.com/latest/Content/Language/System%20Functions/… ) i nowym kluczowym operatorem ( help.dyalog.com/latest/Content/Language/Primitive%20Operators/… ):g⌷⍨⊂⍒2⌷⍉g←{⍺,≢⍵}⌸('\w+'⎕s'\0')⍞
ngn
8

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

(przez LINQPad w trybie „C # Instrukcje”, bez ciągu wejściowego)

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

Nie golfowany:

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

Wyniki:

Wyniki

Wersja 2: 114c

( [\w]obejmuje _, co jest niepoprawne !; [A-z]obejmuje [ \ ] ^ _ `; ustawianie [^_\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();

Nie golfowany:

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

Wyniki: (jako wersja 1)

jimbobmcgee
źródło
Nawiasem mówiąc, dla wersji 2 twoja wersja bez golfa nie pasuje do twojej wersji golfowej. A ponieważ używasz literału, możesz pisać@"[^_\W]"
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨d̷̰̀ĥ̷̳ - naprawiono literówkę i usunąłem dodatkowe `` za 1-znakową oszczędność - dzięki !!
jimbobmcgee
7

R, 58 znaków

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

Stosowanie:

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
źródło
Jest to krótszy (49 znaków) sort(table(gsub("[[:punct:]]","",scan(,""))),d=T). Niestety oba rozwiązania nie działają poprawnie wouldn't.
djhurio
6

perl6: 49 znaków

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

Połącz dane wejściowe w celu dopasowania elementów \w+, umieść wynikową listę słów w a Bag, poproś o ich pary i posortuj je według wartości ujemnej. (To *jest gwiazda typu cokolwiek , tutaj się nie rozmnaża)

wydajność:

"a" => 2
"This" => 1
"is" => 1
"text" => 1
"and" => 1
"number" => 1
"31" => 1
Ayiko
źródło
3
Perl 6 mnie przeraża.
primo
1
Za każdym razem, gdy myślę o fajnej funkcji językowej, szukam jej i jest ona gdzieś w Perl6. Dlatego zajmuje to dużo czasu ...
Phil H
Możesz przyciąć 6 znaków, używając .wordszamiast .comb(/\w+/):)
Mouq
@Mouq: niestety .wordsnie rozebrać :albo .z wejścia wymagane :(
Ayiko
-1. _nie powinny być zawarte w słowie pod opisem problemu.
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)

Teraz działa z 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
daniero
źródło
Nie działa to, gdy w tekście są znaki nowego wiersza lub więcej niż jedno kolejne miejsce.
klingt.net
@ klingt.net naprawiony.
daniero
6

PHP - 84 bajty

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

Dane wejściowe są akceptowane jako argument wiersza poleceń, np .:

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

Dane wyjściowe dla przykładowego ciągu:

Array
(
    [a] => 2
    [number] => 1
    [31] => 1
    [and] => 1
    [text] => 1
    [is] => 1
    [This] => 1
)
primo
źródło
1
mówi, że wejście jest tym, czego chcesz. więc możesz uzyskać go jako parametr wiersza poleceń, używając$argv[1]
Einacio
@Einacio dobre połączenie.
primo
-1. Podkreślenie _nie powinno być zawarte w słowie.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨d̷̰̀ĥ̷̳
@ n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨d̷̰̀ĥ̷̳ naprawione.
primo
5

PowerShell (40)

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

$ s jest zmienną zawierającą łańcuch wejściowy.

drobnoustrój
źródło
2
[\W]nie wystarcza - w moim teście pasuje do miejsca. I nie jest uporządkowane według malejącej liczby ...
jimbobmcgee
$s -split"[\W]"|group -ca|where{$_.Name -ne ""}|sort{-$_.Count}zbliża cię (oczywiście z kosztami)
jimbobmcgee
Ups, przegapiłem część sortowania. Wkrótce naprawię moją odpowiedź.
mikrobian
alternatywnie:$s -split"\W+"|group -ca |sort count -des
Nacimota
4
-split"\W+"dopasowuje pusty ciąg między ostatnim .a końcem ciągu; także \W+mecze, _które technicznie nie są dozwolone
jimbobmcgee
4

Perl 69

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

Dodano rekomendacje od @primo i @protist

Dom Hastings
źródło
1
Co z sortowaniem?
daniero
@daniero, doskonały punkt! To teraz sortuje!
Dom Hastings
1
Myślę, że to tak zwięzłe, jak to możliwe. Jeśli nie przeszkadza ci ostrzeżenie o wycofaniu, pomiędzy gei nie trzeba wstawiać spacji for. Ponadto <=>operator może zostać zastąpiony przez -.
primo
2
@primo Ahhh -zamiast <=>jest geniuszem, nie jestem pewien, czy jest to wskazówka dla golfistów dla wątku Perla. Zaktualizuję to później, dzięki!
Dom Hastings
1
Hej @protist, \wzawiera również liczby ( perl -e 'print for"a 1 2 3 4 b"=~/\w/g'drukuje a1234b), ale twój mechanizm iteracji słów zapisuje inny znak, więc zaktualizuję. Dziękuję Ci!
Dom Hastings
4

PowerShell: 57 55 53 62 57

(bez ciągu wejściowego)

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

zwraca:

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}

(z rekwizytami do @microbian dla grupy -ca)

jimbobmcgee
źródło
3

EcmaScript 6

Wersja 1 (108 znaków)

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

Wersja 2 (102 znaki)

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

Wersja 3 (105 znaków)

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

Wersja 4 (94 znaki)

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

Wersja 5 (bez alertu; 87 znaków)

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

Wersja 6 (100 znaków)

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

Wydajność:

a:2
31:1
This:1
is:1
text:1
and:1
number:1
Szczoteczka do zębów
źródło
Możesz zmienić _[a]i _[b]do _.ai _.b. Również zmiana /\w+/g,_={}na _=/\w+/gprzyniesie ten sam wynik.
wyjechał
@eithedog Dziękujemy! Jednak nie mogę zmienić _[a]się _.a, ponieważ próbuje uzyskać dostęp do nieruchomości "a"z _, a nie nieruchomości a.
Szczoteczka do zębów
ah, prawda - kolejność nie zostanie zachowana.
Kontynuuj
Och, nie zauważyłem twojej odpowiedzi ... miło. Ale .. Object.keysstaje się globalnym w ES6? Twoja odpowiedź wydaje się zakładać, że tak jest, ale nie pamiętam, aby było to zaplanowane na ES6.
FireFly
@FireFly Nie mogę znaleźć żadnej dokumentacji, ale działa poprawnie w przeglądarce Firefox. Nie testowałem tego w Chrome / Opera / IE.
Szczoteczka do zębów
3

Groovy 77 82

zmieniono wyrażenie regularne z [^\w]+na [^\d\p{L}]+, aby rozwiązać problem z podkreśleniem

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}

bez pierwszego wiersza, 82 znaki

wydajność:

[a:2, This:1, is:1, text:1, and:1, number:1, 31:1]
Kamil Mikołajczyk
źródło
nu_bernie jest alfanumeryczny. To powinno być 2 słowa
Cruncher
Dlaczego warto korzystać nu_berzamiast number?
Kevin Fegan
Wprowadzono mnie w błąd przez inne posty;) teraz usunąłem „_” z wejścia, ale poprawiłem regex, aby sobie z tym poradzić
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

Chociaż gawk asortdziała na tablicach asocjacyjnych, najwyraźniej nie zachowuje wartości indeksu, co wymaga zewnętrznegosort

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

Nieco większe, ale czyste rozwiązanie gawk, używane PROCINFOdo ustawienia domyślnej kolejności sortowania dla tablicy asocjacyjnej (wydaje się, że wymaga stosunkowo nowego gawk -> 4.x?)

BEGIN{RS="\\W+";PROCINFO["sorted_in"]="@val_num_desc"}
{c[$0]++}
END{for(w in c)print c[w],w}
steeldriver
źródło
Ooooch Nie wiedziałem o PROCINFO. Jakbym potrzebowała kolejnej wymówki, aby użyć awk w moim życiu. Przeklnij cię!
dmckee
@dmckee TBH Nie wiedziałem o PROCINFO, dopóki nie zacząłem się grzebać - byłem przekonany, że musi być sposób na zrobienie tego natywnie - szkoda tylko, że identyfikatory są tak długie;)
steeldriver
W dawnych złych czasach po prostu nie było sposobu. Co prowadzi do rzeczy takich jak ta moja stara odpowiedź .
dmckee
-1. Podkreślenie _nie powinno być zawarte w słowie.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨d̷̰̀ĥ̷̳
3

JavaScript - 132 126 znaków!

(Najkrótszy kod 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]})

Poprawiono wyrażenia regularne i niektóre zmiany.


Nie golfił

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 = "Jak błyszczący jest ten dzień, nie jest"

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


Stary - 156 143 141 140 132 znaków

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

Po raz pierwszy zagrał w golfa. Doceniono opinie.

Gaurang Tandon
źródło
2

EcmaScript 6, 115 100 87 (bez monitu i ostrzeżenia)

Dzięki @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])

Z monitem i ostrzeżeniem (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]))

Uruchom go w przeglądarce Firefox.

teh_senaus
źródło
1
Nie trzeba var . Ponadto, można przesunąć a={}do środka prompt- prompt(a={}). Możesz także upuścić Object.i zmienić w=>a[w]=a[w]+1||1naw=>a[w]=-~a[w]
eithed
Bardzo dobrze.
Pokonuje
To samo, co w odpowiedzi na szczoteczkę @ - przeniesienie deklaracji az monitu na regexp pozwoli zaoszczędzić dwa kolejne znaki.
wyjechał
Jest ładnie i czysto. Dobra robota!
Szczoteczka do zębów
-1. Podkreślenie _nie powinno być zawarte w słowie.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨d̷̰̀ĥ̷̳
2

Rubin 58 82 65

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

Testowe uruchomienie:

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

Edytuj 58-> 80: Ok, byłem daleko. Zapomniałem posortować słowa według zdarzeń. Ponadto Array#uniqnie jest urządzeniem wyliczającym, ale używa danego bloku do porównywania elementów, więc przekazanie putsgo nie odfiltrowało duplikatów (nie oznacza to, że powinniśmy).

daniero
źródło
1
Może split(/\W+/)zamiast scan(niesprawdzony)?
Howard
@ Howard Thanks. \Wwyklucza, _więc trzeba było to naprawić, ale nadal zapisywało 2 znaki (potem dodałem 20, aby naprawić sortowanie, które zaniedbałem).
daniero
Nie należy go sortowaćreverse (a=gets.split(/[_\W]+/)).uniq.map{|w|[w,a.count(w)]}.sort_by(&:last).reverse.map{|x|p x}
Eduard Florinescu
@EduardFlorinescu Nah. reversejest zbyt gadatliwy;) Przy okazji, zmiana pytania jest niesprawiedliwa.
daniero
Jeśli widzisz w próbce wyjściowej, był posortowany malejąco tylko, że zapomniałem go podać.
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"))

Dane wyjściowe po wywołaniu z 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 = ()

Aktualizacja: Niektóre wyjaśnienia zgodnie z żądaniem w komentarzach.

Używa funkcji set do generowania tablicy znaków niealfanumerycznych na wejściu w celu przekazania do String.Split, a następnie używa funkcji sekwencji do odfiltrowywania pustych ciągów, generowania liczby słów i drukowania wyniku.

Kilka sztuczek golfowych: Dodaje pusty ciąg do argumentu funkcji s, aby wymusić wnioskowanie o typie argumentu jako ciąg zamiast jawnego deklarowania typu. Używa Seq.where zamiast Seq.filter do zapisania kilku znaków (są to synonimy). Miksuje potok przedni i zwykłą aplikację funkcji w celu zminimalizowania znaków. Używa curry i (op) składni do leczenia <> ~ - i <|| operatory jako zwykłe funkcje, aby uniknąć deklarowania lambda do filtrowania pustych ciągów, sortowania według malejącej liczby i drukowania krotek.

mattnewport
źródło
Zdecydowanie powinieneś podać jakieś wyjaśnienie; w ten sposób możemy zrozumieć Twój kod.
Justin
Dodano wersję degolfed i wyjaśnienie.
mattnewport
2

Python - 95 (teraz 87 dzięki @primo)

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

Przykładowe dane wejściowe:

'This is a text and a number: 31'

Przykładowe dane wyjściowe:

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

Wszelkie sugestie dotyczące poprawy będą mile widziane

Azwr
źródło
1
Rozwiązanie jest dobre, ale dane wyjściowe nie są sortowane.
Eduard Florinescu
Co rozumiesz przez posortowane? Dziękuję za komentarz.
Azwr
1
\wmecze [a-zA-Z0-9_]. Cały regex może zostać zastąpiony przez r'\w+'. Ponadto xzmienna nie jest potrzebna, wystarczy użyć jej raw_input()jako drugiego parametru do findall.
primo
Po sortowaniu PO oznacza, że ​​najczęściej pojawiające się słowa muszą być wymienione na początku. Ponadto twój program powinien zawierać printinstrukcję (tj. print map(...), W przeciwnym razie nie będzie to kompletny program.
primo
Nie mam teraz czasu na sortowanie :(
Spieszy
2

JavaScript 160 144 (edytowany: w celu spełnienia wymagań)

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

Rejestruje kolejno każde słowo w konsoli, przekazując następujący ciąg:

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

Wyjścia:

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 

Nie mam serca do użycia alert().

George Reith
źródło
1
Sortuj według liczby. wystąpień, więc youpowinno być pierwsze.
Eduard Florinescu
@EduardFlorinescu Silly me ... Naprawię to później.
George Reith,
@EduardFlorinescu naprawiono
George Reith
-1. Podkreślenie _nie powinno być zawarte w słowie.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨d̷̰̀ĥ̷̳
++o[a]||1=>-~o[a]
l4m2
2

k [71 znaków]

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

Każdy inny znak oprócz znaków alfanumerycznych będzie traktowany jako separator.

przykład

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

przykład

f "won't won won-won"
won| 4
t  | 1
nyi
źródło
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)

Zapętla każdą możliwą liczbę dopasowań w kolejności malejącej i wyprowadza słowa z taką liczbą wystąpień. Żeby być okropnym.

Uwagi: Alert skróciłby niektóre długości. Ściśle mówiąc alfanumeryczny powinien być[^\W_]

Zachary Vance
źródło
2

Haskell (153 = kod 104 + import 49)

Całkiem prosta, całkowicie skomponowana funkcja ... nawet argument nie jest konieczny! To jest mój pierwszy golf, więc może spokojnie? :)

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

Wydajność:

*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
źródło
2

q (50)

desc count each group" "vs ssr[;"[^0-9A-Za-z]";" "]
  • ssr zastępuje nie alfanumeryczne
  • „” vs dzieli wynik na listę symboli
  • liczyć każda grupa liczy tworzy dict dopasowujący różne elementy listy do liczby wystąpień
  • desc sortuje dykt według malejących wartości

edycja: naprawiono przypadkowo pasujące ascii 58-64 i 91-96

nightTrevors
źródło
1
Nie mam wiedzy, qale czy jest [0-z]oparty na wyrażeniach regularnych ASCII? Jeśli tak, to czy nie zawiera również znaków ASCII 58–64? Ponieważ one są : ; < = > ? @.
jimbobmcgee
Świetny chwyt jimbob, dzięki
nightTrevors
Nie ma za co; tylko zauważył, ponieważ znalazłem to samo w C #. Niestety, to samo z [A-z], które pasuje do ASCII 91-96, które są `[\] ^
_`
Ach, masz rację, ładna lekcja Ascii właśnie tam!
nightTrevors
Właśnie odkryłem [^_\W]+dla mojego, który powinien być „wyklucz znaki niebędące wyrazami i podkreślenie” , jeśli twoja składnia obsługuje \Wklasę ...
jimbobmcgee
2

Pure Bash (bez programów zewnętrznych), 164

Jest to dłuższe niż się spodziewałem, ale chciałem sprawdzić, czy konieczne liczenie i sortowanie (we właściwym kierunku) można wykonać wyłącznie za pomocą bashtablic (asocjacyjnych i niesocjacyjnych):

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

Zapisz jako plik skryptu chmod +xi uruchom:

$ ./countoccur To jest tekst i liczba: 31.
a: 2
i 1
numer 1
tekst: 1
31: 1
to: 1
To: 1
$ 
Cyfrowa trauma
źródło
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-"}'

Wykonuje pracę bez gawkish rozszerzenia:

$ 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

Jeśli zamiast tego wypiszesz „count: word”, byłoby to nieco krótsze, ale chciałem naśladować dane wyjściowe z podanego przykładu ...


źródło
2

Tcl , 99 bajtów

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

Wypróbuj online!

sergiol
źródło
1

Python 2.X (108 - Znaki)

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

Python 3.X (106 - Znaki)

print('\n'.join('{}:{}'.format(a,b)for a,b in __import__("collections").Counter(input().split()).items())
Abhijit
źródło
Separators will be anything that is not alpha-numeric- Dzielisz się tylko na białych znakach.
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
źródło
Nie spełnia warunku, że znak niealfanumeryczny powinien być separatorem.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨d̷̰̀ĥ̷̳
1

Python 3 - 76

Wymóg podziału na znaki niealfanumeryczne niestety rozszerza kod o 19 znaków. Dane wyjściowe następujących elementów są wyświetlane poprawnie. Jeśli nie jesteś pewien, dodaj .most_common()po .Counter(...).

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

Wejście / Wyjście

Biorąc pod uwagę wkład This is a text and a number: 31.otrzymujesz następujące dane wyjściowe:

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

Próbowałem z innymi wartościami, takimi jak

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

w celu zapewnienia, kolejność wyjściowa nie zależy od wartości / wartości skrótu klucza. Ten przykład daje:

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

Ale jak powiedziałem, print(i('collections').Counter(i('re').findall('\w+',input())).most_common())wróci wyniki jako zdecydowanie uporządkowanej listy krotek.


Python 3 - 57 (jeśli wystarczy miejsce do podziału: P)

print(__import__('collections').Counter(input().split()))
Dave J.
źródło
Jeśli założyłeś, że łańcuch zawiera się w niektórych zmiennych s, podobnie jak niektóre inne odpowiedzi, możesz stracić 6 znaków, zastępując input ().
Phil H
@ PhhH well. masz rację, ale nigdy nie przeczytałbym tego z wymagań. pewnie „ciąg dla JavaScriptu” może to sugerować, ale nie mogę z czystym sumieniem interpretować zmiennej ciąg jako prawidłowego „wejścia”. Ale masz rację. skróciłoby to jeszcze bardziej. : P
Dave J
-1. Podkreślenie _nie powinno być zawarte w słowie.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨d̷̰̀ĥ̷̳
Zależy to od definicji alfanumerycznej. W Pythonie „\ w” jest zdefiniowany do akceptowania znaków alfanumerycznych. Być może masz rację, ale przy takiej interpretacji zasad moje rozwiązanie jest nadal poprawne. :)
Dave J