1
$\begingroup$

Given the following string:

sentence = "Never in the delirious dream of a disordered brain could 
anything more savage, more appalling, more hellish, be conceived than 
that dark form and savage face which broke upon us out of the wall of 
fog";

I am trying to find the frequency of occurrence of each letter. Working towards this, I have find the occurrence of each letter by:

CountLettersSorted[y_] := 
  Reverse[SortBy[
  Tally[Characters[
  StringReplace[
   ToLowerCase[y], {"," -> "", " " -> "", "." -> "", 
    "-" -> ""}]]], Last]];

Giving:

{{"e", 39}, {"a", 35}, {"s", 26}, {"n", 25}, {"o", 24}, {"l", 
  24}, {"t", 23}, {"d", 21}, {"u", 17}, {"i", 17}, {"h", 17}, {"r", 
  14}, {"m", 13}, {"w", 11}, {"c", 11}, {"y", 9}, {"b", 9}, {"p", 
  7}, {"k", 7}, {"v", 6}, {"g", 6}, {"f", 3}}

Now I'm trying to define a function f that can be mapped to this list ie:

f:= #/Length[string[s]]
findingfrequency=Map[f,#]   

But this is not working, any ideas?

$\endgroup$
  • $\begingroup$ If you use # in your code, you also need & (this marks the end of the anonymous function). For your specific case, I would suggest ReverseSort[Counts[Characters[…]]] to get an association of the counts. Then all you need is counts/Length["..."] to get the frequencies. (The advantage of an association here is that the keys (the letters) are ignored for many operations, so dividing by the length leaves them alone) $\endgroup$ – Lukas Lang Nov 11 '18 at 12:39
4
$\begingroup$

Why not use LetterCounts

LetterCounts[sentence, IgnoreCase -> True] // KeySort

N[#]/Total[#] &[%]
<|"a" -> 16, "b" -> 3, "c" -> 5, "d" -> 9, "e" -> 19, "f" -> 6, 
  "g" -> 5, "h" -> 9, "i" -> 10, "k" -> 2, "l" -> 8, "m" -> 5, 
  "n" -> 10, "o" -> 15, "p" -> 3, "r" -> 12, "s" -> 6, "t" -> 7, 
  "u" -> 5, "v" -> 4, "w" -> 2, "y" -> 1|>

<|"a" -> 0.0987654, "b" -> 0.0185185, "c" -> 0.0308642, 
  "d" -> 0.0555556, "e" -> 0.117284, "f" -> 0.037037, "g" -> 0.0308642,
  "h" -> 0.0555556, "i" -> 0.0617284, "k" -> 0.0123457, 
  "l" -> 0.0493827, "m" -> 0.0308642, "n" -> 0.0617284, 
  "o" -> 0.0925926, "p" -> 0.0185185, "r" -> 0.0740741, 
  "s" -> 0.037037, "t" -> 0.0432099, "u" -> 0.0308642, 
  "v" -> 0.0246914, "w" -> 0.0123457, "y" -> 0.00617284|>

BTW, your sentence does not give 39 "e"s.

$\endgroup$
1
$\begingroup$

Not totally sure if this is what you want:

    tallyChars[sentence_String] := Module[{work},
  work = StringCases[Characters[sentence], 
     head___ ~~ LetterCharacter ~~ tail___] /. {} -> Nothing;
  work = Flatten@(ToLowerCase /@ work);
  SortBy[Tally[work], Last] // Reverse
  ]

This can be done shorter, but so it is easy to read:

Step1: get the letter characters and delete the {} coming form punctuation marks etc. Step2: Convert to Lowercase and flatten the list Step3: Sorting

You can then use the function as `tallyChars /@ listOfStrings

remark: your example sentence has only 19 times the letter "e".

$\endgroup$
0
$\begingroup$

Does this not accomplish what you're after?

Reverse[SortBy[
  Tally[ToLowerCase@
    StringCases[sentence, LetterCharacter]], #[[2]] &]]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.