It seems to me you are counting the number of different letters that apear as uppercase and not the total number of uppercase characters present. Here I use the UN Declaration of Human Rights without PunctuationCharacter
as sample text. I use RepeatedTiming
to show the average time in seconds used to compute, together with the result obtained.
Test data
testtext = StringDelete[
ExampleData[{"Text", "UNHumanRightsEnglish"}]
, PunctuationCharacter];
Your approach
RepeatedTiming[
Total[Boole[UpperCaseQ /@ Keys[LetterCounts[testtext]]]]
]
(* {0.0564, 21} *)
What I think you intended
RepeatedTiming[
Total@KeySelect[LetterCounts[testtext], UpperCaseQ]
]
(* {0.059, 185} *)
My approach
RepeatedTiming[
StringCount[testtext, _?UpperCaseQ]
]
(* {0.0032, 185} *)
@C.E. offers the best answer so far, using HammingDistance
. Using a similar approach but with EditDistance
it's the slowest of all.
BarChart[
First /@ {
RepeatedTiming[(* "HammingDistance" @C.E *)
HammingDistance[testtext, ToLowerCase[testtext]]
],
RepeatedTiming[(* "StringCount Alternatives CharacterRange" @C.E *)
StringCount[testtext, Alternatives @@ CharacterRange["A", "Z"]]
],
RepeatedTiming[(* "StringCount RegularExpression" @Mr.Wizard *)
StringCount[testtext, RegularExpression["\\p{Lu}"]]
],
RepeatedTiming[ (* "StringCount UpperCaseQ" @rhermans *)
StringCount[testtext, _?UpperCaseQ]
],
RepeatedTiming[(* "Length@StringCases" *)
Length@StringCases[testtext, _?UpperCaseQ]
],
RepeatedTiming[(* "Total KeySelect LetterCounts" @
KirilDanilchenko *)
Total@KeySelect[LetterCounts[testtext], UpperCaseQ]
],
RepeatedTiming[(* "EditDistance" @rhermans *)
EditDistance[testtext, ToLowerCase[testtext]]
]
} 10^6
, ChartLabels -> {
"HammingDistance\[email protected]",
"StringCount\nAlternatives\nCharacterRange\[email protected]",
"StringCount\nRegularExpression\[email protected] ",
"StringCount\nUpperCaseQ\n@rhermans",
"Length@StringCases",
"Total\nKeySelect\nLetterCounts\n@KirilDanilchenko",
"EditDistance\n@rhermans"
}
, PlotTheme -> "Scientific"
, AspectRatio -> 1/2
, ImageSize -> 600
, FrameLabel -> {None, "Time \[Mu]s"}
, BarSpacing -> Large
, ScalingFunctions -> "Log"
]

StringCount
. $\endgroup$