0

# Character Occurrences Count

Hello,

I'm wondering if there's a way to count how many times a given character is in a string.

i.e.: I have the field 'mytext' which contains a string (let's say "rockandrollwillneverdie") and I want to find out how many times the letter "e" appears in the string (so the result should be "3".

36replies Oldest first
• Oldest first
• Popular
• And a proposal for the complete computation of the checksum (boy, I had some spare time today, and it rains):

``````let xCarDis := substr(cfparz, 0, 1) + substr(cfparz, 2, 1) + substr(cfparz, 4, 1) + substr(cfparz, 6, 1) + substr(cfparz, 8, 1) + substr(cfparz, 10, 1) + substr(cfparz, 12, 1) + substr(cfparz, 14, 1);
let xCarPar := substr(cfparz, 1, 1) + substr(cfparz, 3, 1) + substr(cfparz, 5, 1) + substr(cfparz, 7, 1) + substr(cfparz, 9, 1) + substr(cfparz, 11, 1) + substr(cfparz, 13, 1);
let xCarList := "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
let xParFact := [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let xDisFact := [1, 0, 5, 7, 9, 13, 15, 17, 19, 21, 2, 4, 18, 20, 11, 3, 6, 8, 12, 14, 16, 10, 22, 25, 24, 23, 1, 0, 5, 7, 9, 13, 15, 17, 19, 21];
let sumPD := sum(for i in range(0, length(xCarList)) do
countLetters(xCarPar, item(xCarList, i)) * item(xParFact, i) + countLetters(xCarDis, item(xCarList, i)) * item(xDisFact, i)
end);
let resto := (sumPD / 26 - floor(sumPD / 26)) * 26;
let finalC := item("ABCDEFGHIJKLMNOPQRSTUVWXYZ", round(resto));``````
Like 4
• Gianluca
• Gianluca
• 4 mths ago
• Reported - view

Alain Fontaine black magic happens! :)

I'm trying to understand your formula, which works perfectly: you created two different strings for multipliers (xParFact and xDisFact) and used them to multiply the xCarList string.

I assume that for it to work, length of both strings has to be the same, correct?

Thanks for all the time you spent on it!

Like
• Gianluca Yes, the three strings must have the same length. The same applies for the latest way to compute the checksum, of course.

Like
• John Halls
• John_Halls
• 4 mths ago
• Reported - view

https://en.wikipedia.org/wiki/Italian_fiscal_code

I would break down each part (surname, first name, etc) into its own field and calculation and then concatenate all the fields into the fiscal code at the end

Like 1
• Gianluca
• Gianluca
• 4 mths ago
• Reported - view

John Halls that was my same approach....i usually break down things to their more simple component and then combine them. But once i got there i wanted put everything in one field. Which brings me to ask this: beside reducing the number of fields, is there any advantage in having all the code in one single formula instead of having it  spread into different fields?

Like
• Gianluca
• Gianluca
• 4 mths ago
• Reported - view

here's the final code after all the suggestions: from 211 to 35 lines.

``````let xPCog := replace(Cognome, " ", "");
let xConCog := replacex(upper(xPCog), "A|E|I|O|U", "g", "");
let xVocCog := replacex(upper(xPCog), "B|C|D|F|G|H|J|K|L|M|N|P|Q|R|S|T|V|W|X|Y|Z", "g", "");
let xCog := xConCog + xVocCog;
let xPNom := replace(Nome, " ", "");
let xConNom := replacex(upper(xPNom), "A|E|I|O|U", "g", "");
let xVocNom := replacex(upper(xPNom), "B|C|D|F|G|H|J|K|L|M|N|P|Q|R|S|T|V|W|X|Y|Z", "g", "");
let xNom := xConNom + xVocNom;
let Mese := item("0ABCDEHLMPRST", round(month(DataNascita)));
let cfparz := rpad(substring(text(xCog), 0, 3), 3, "X") + if length(text(xConNom)) > 3 then
substring(text(xNom), 0, 1) + substring(text(xNom), 2, 4)
else
end + substring(text(year(DataNascita)), 2, 4) + Mese + switch Sesso do
case 1:
format(day(DataNascita), "00")
case 2:
text(day(DataNascita) + 40)
default:
""
end + (
let xComune := text(Luogodinascita);
(select Comuni where Comune = xComune).CodiceComune
);
let xCarDis := substr(cfparz, 0, 1) + substr(cfparz, 2, 1) + substr(cfparz, 4, 1) + substr(cfparz, 6, 1) + substr(cfparz, 8, 1) + substr(cfparz, 10, 1) + substr(cfparz, 12, 1) + substr(cfparz, 14, 1);
let xCarPar := substr(cfparz, 1, 1) + substr(cfparz, 3, 1) + substr(cfparz, 5, 1) + substr(cfparz, 7, 1) + substr(cfparz, 9, 1) + substr(cfparz, 11, 1) + substr(cfparz, 13, 1);
let xCarList := "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
let xParFact := [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let xDisFact := [1, 0, 5, 7, 9, 13, 15, 17, 19, 21, 2, 4, 18, 20, 11, 3, 6, 8, 12, 14, 16, 10, 22, 25, 24, 23, 1, 0, 5, 7, 9, 13, 15, 17, 19, 21];
let sumPD := sum(for i in range(0, length(xCarList)) do
countLetters(xCarPar, item(xCarList, i)) * item(xParFact, i) + countLetters(xCarDis, item(xCarList, i)) * item(xDisFact, i)
end);
let resto := (sumPD / 26 - floor(sumPD / 26)) * 26;
let finalC := item("ABCDEFGHIJKLMNOPQRSTUVWXYZ", round(resto));
cfparz + finalC
``````
Like
• I suspected that such a convoluted specification could only come from an administration 8-). So, knowing the specification, I am submitting my last word on the subject. As you probably already remarked, I *love* regular expressions. And the computation of the checksum does not use the character counting function, but a simpler and probably more efficient method, despite the fact that this thread was started by a question about character counting.

``````let xPCog := replace(upper(Cognome), " ", "");
let xConCog := replacex(xPCog, "[AEIOU]", "g", "");
let xVocCog := replacex(xPCog, "[BCDFGHJKLMNPQRSTVWXYZ]", "g", "");
let xCog := substr(xConCog + xVocCog + "XXX", 0, 3);
let xPNom := replace(upper(Nome), " ", "");
let xConNom := replacex(xPNom, "[AEIOU]", "g", "");
let xNom := if length(xConNom) > 3 then
extractx(xConNom, "^(.).(..)", "\$1\$2")
else
let xVocNom := replacex(xPNom, "[BCDFGHJKLMNPQRSTVWXYZ]", "g", "");
substr(xConNom + xVocNom + "XXX", 0, 3)
end;
let cfparz := xCog + xNom + substring(text(year(DataNascita)), 2, 4) + item("ABCDEHLMPRST", month(DataNascita) - 1) + switch Sesso do
case 1:
format(day(DataNascita), "00")
case 2:
text(day(DataNascita) + 40)
default:
""
end + (
let xComune := text(ComuneNascita);
(select Comuni where Comune = xComune).CodiceComune
);
let xCarList := "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
let xParFact := [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
let xDisFact := [1, 0, 5, 7, 9, 13, 15, 17, 19, 21, 2, 4, 18, 20, 11, 3, 6, 8, 12, 14, 16, 10, 22, 25, 24, 23, 1, 0, 5, 7, 9, 13, 15, 17, 19, 21];
let sumPD := sum(for c in replacex(cfparz, ".(.)?", "g", "\$1") do
item(xParFact, index(xCarList, c))
end) + sum(for c in replacex(cfparz, "(.).?", "g", "\$1") do
item(xDisFact, index(xCarList, c))
end);
let finalC := item("ABCDEFGHIJKLMNOPQRSTUVWXYZ", sumPD % 26);
cfparz + finalC
``````
Like 2
• Gianluca
• Gianluca
• 4 mths ago
• Reported - view

Alain Fontaine I'm charmed by Regex too....but I get lost when i try to "decode" them :9

Once again, thank you.

Like
• Gianluca Of course, regular expressions are well known to be "write only" .

Like 1
• Gianluca
• Gianluca
• 4 mths ago
• Reported - view

Alain Fontaine you'll forgive me if I try to steal you just one more advice. Let's say I want to make this a custom function, I wrote:

function calcolocf(Cognome : text, Nome : text, DataNascita : date, Sesso : XXXXX, ComuneNascita: text) do

and then all the script above.

What kind of data type am I supposed to use to reference Sesso, since it is a Choice type field? Function's syntax seems not to recognize "choice" as a valid data type.

Like
• Unless someone knows better, I would declare the parameter to be a "number", and call the function with number(Sesso) as parameter.

Like 2
• Hi, sorry to interrupt in this thread, but my case is relevant I think.

Could someone have a look at my thread ?

Seek help to find array position number in a array loop - Get help - Ninox Community

It boils down to count the commas in a string, example image:  count the commas to red 00070 without having red 04070 earlier in string messing up the counting.

regards,

Håvard

Like
Like Follow