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

36 replies

null
    • Alain_Fontaine
    • 2 yrs ago
    • Reported - view

    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));
      • Gianluca
      • 2 yrs 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!

      • Alain_Fontaine
      • 2 yrs ago
      • Reported - view

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

    • John_Halls
    • 2 yrs 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

      • Gianluca
      • 2 yrs 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? 

    • Gianluca
    • 2 yrs 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
            rpad(substring(text(xNom), 0, 3), 3, "X")
        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
    
    • Alain_Fontaine
    • 2 yrs ago
    • Reported - view

    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
    
      • Gianluca
      • 2 yrs 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.

      • Alain_Fontaine
      • 2 yrs ago
      • Reported - view

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

      • Gianluca
      • 2 yrs 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.

    • Alain_Fontaine
    • 2 yrs ago
    • Reported - view

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

    • Haavard_Hjorteland
    • 2 yrs ago
    • Reported - view

    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

Content aside

  • Status Answered
  • 2 yrs agoLast active
  • 36Replies
  • 541Views
  • 6 Following