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
-
Hi Gianluca,
with length() you get the length of a string and use it for iteration. With substring() you can get a character from a string. Then you compare and Bob's your uncle:
let mystring := "rockandrollwillneverdie"; let found := 0 for i from 0 to length(mystring) do if substring(mystring, i, i+1) = "e" then found := found + 1; end; end; alert(found)
-
thank you Lars,
it works perfectly, but this way i get the result in an alert pop-up. Can I get te same result as a number and use it in further calculations?
-
Lars Thank you so much! This was the missing piece of a longer script that i needed to bring into ninox from a filemaker custom function i used! Now I think i'll be able to finish it!
-
And I forgot: if you need this more than once in your script, you can define it as a function:
function countLetters(myString : text, myLetter : text) do let found := 0 for i from 0 to length(myString) do if substring(myString, i, i+1) = myLetter then found := found + 1; end; end; found; end; let e := countLetters("rockandrollneverdies", "e"); let d := countLetters("rockandrollneverdies", "d")
The last two lines are just examples on how to use it. You need to define the function at the very beginning of your script.
-
Another way to solve such a problem would be to harness the power of regular expressions, replacing the loop by:
length(replacex(myString, "[^" + myLetter + "]", "g", ""))
-
Ok. Thanks to your suggestions i've finalized the script (which is about 211 lines long.
I embedded Alain Fontaine script in the function Lars have created and all works perfectly. Now I just wonder if there are ways to "clean" it and make it shorter or more tidy.
For the brave ones who dare to read it i post it here.
function countLetters(myString : text,myLetter : text) do length(replacex(myString, "[^" + myLetter + "]", "g", "")) end; 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 xLunCog := length(xCog); 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 xLunNom := length(xNom); let cfparz := switch xLunCog do case 1: text(xConCog) + "XX" case 2: text(xConCog) + "X" case 3: text(xConCog) default: substring(text(xCog), 0, 3) end + switch xLunNom do case 1: text(xConNom) + "XX" case 2: text(xConNom) + "X" case 3: text(xNom) default: if length(text(xConNom)) > 3 then substring(text(xNom), 0, 1) + substring(text(xNom), 2, 4) else substring(text(xNom), 0, 3) end end + substring(text(year(DataNascita)), 2, 4) + switch text(month(DataNascita)) do case "1": "A" case "2": "B" case "3": "C" case "4": "D" case "5": "E" case "6": "H" case "7": "L" case "8": "M" case "9": "P" case "10": "R" case "11": "S" case "12": "T" default: "" end + switch Sesso do case 1: if length(text(day(DataNascita))) = 1 then "0" + text(day(DataNascita)) else text(day(DataNascita)) end case 2: text(day(DataNascita) + 40) default: "" end + ( let xComune := text(ComuneNascita); (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 a := countLetters(xCarPar, "A"); let b := countLetters(xCarPar, "B"); let c := countLetters(xCarPar, "C"); let d := countLetters(xCarPar, "D"); let e := countLetters(xCarPar, "E"); let f := countLetters(xCarPar, "F"); let g := countLetters(xCarPar, "G"); let h := countLetters(xCarPar, "H"); let i := countLetters(xCarPar, "I"); let j := countLetters(xCarPar, "J"); let k := countLetters(xCarPar, "K"); let l := countLetters(xCarPar, "L"); let m := countLetters(xCarPar, "M"); let n := countLetters(xCarPar, "N"); let o := countLetters(xCarPar, "O"); let p := countLetters(xCarPar, "P"); let q := countLetters(xCarPar, "Q"); let r := countLetters(xCarPar, "R"); let s := countLetters(xCarPar, "S"); let t := countLetters(xCarPar, "T"); let u := countLetters(xCarPar, "U"); let v := countLetters(xCarPar, "V"); let w := countLetters(xCarPar, "W"); let x := countLetters(xCarPar, "X"); let y := countLetters(xCarPar, "Y"); let z := countLetters(xCarPar, "Z"); let x0 := countLetters(xCarPar, "0"); let x1 := countLetters(xCarPar, "1"); let x2 := countLetters(xCarPar, "2"); let x3 := countLetters(xCarPar, "3"); let x4 := countLetters(xCarPar, "4"); let x5 := countLetters(xCarPar, "5"); let x6 := countLetters(xCarPar, "6"); let x7 := countLetters(xCarPar, "7"); let x8 := countLetters(xCarPar, "8"); let x9 := countLetters(xCarPar, "9"); let sumP := a * 0 + b * 1 + c * 2 + d * 3 + e * 4 + f * 5 + g * 6 + h * 7 + i * 8 + j * 9 + k * 10 + l * 11 + m * 12 + n * 13 + o * 14 + p * 15 + q * 16 + r * 17 + s * 18 + t * 19 + u * 20 + v * 21 + w * 22 + x * 23 + y * 24 + z * 25 + x0 * 0 + x1 * 1 + x2 * 2 + x3 * 3 + x4 * 4 + x5 * 5 + x6 * 6 + x7 * 7 + x8 * 8 + x9 * 9; let aa := countLetters(xCarDis, "A"); let bb := countLetters(xCarDis, "B"); let cc := countLetters(xCarDis, "C"); let dd := countLetters(xCarDis, "D"); let ee := countLetters(xCarDis, "E"); let ff := countLetters(xCarDis, "F"); let gg := countLetters(xCarDis, "G"); let hh := countLetters(xCarDis, "H"); let ii := countLetters(xCarDis, "I"); let jj := countLetters(xCarDis, "J"); let kk := countLetters(xCarDis, "K"); let ll := countLetters(xCarDis, "L"); let mm := countLetters(xCarDis, "M"); let nn := countLetters(xCarDis, "N"); let oo := countLetters(xCarDis, "O"); let pp := countLetters(xCarDis, "P"); let qq := countLetters(xCarDis, "Q"); let rr := countLetters(xCarDis, "R"); let ss := countLetters(xCarDis, "S"); let tt := countLetters(xCarDis, "T"); let uu := countLetters(xCarDis, "U"); let vv := countLetters(xCarDis, "V"); let ww := countLetters(xCarDis, "W"); let xx := countLetters(xCarDis, "X"); let yy := countLetters(xCarDis, "Y"); let zz := countLetters(xCarDis, "Z"); let xx0 := countLetters(xCarDis, "0"); let xx1 := countLetters(xCarDis, "1"); let xx2 := countLetters(xCarDis, "2"); let xx3 := countLetters(xCarDis, "3"); let xx4 := countLetters(xCarDis, "4"); let xx5 := countLetters(xCarDis, "5"); let xx6 := countLetters(xCarDis, "6"); let xx7 := countLetters(xCarDis, "7"); let xx8 := countLetters(xCarDis, "8"); let xx9 := countLetters(xCarDis, "9"); let sumD := aa * 1 + bb * 0 + cc * 5 + dd * 7 + ee * 9 + ff * 13 + gg * 15 + hh * 17 + ii * 19 + jj * 21 + kk * 2 + ll * 4 + mm * 18 + nn * 20 + oo * 11 + pp * 3 + qq * 6 + rr * 8 + ss * 12 + tt * 14 + uu * 16 + vv * 10 + ww * 22 + xx * 25 + yy * 24 + zz * 23 + xx0 * 1 + xx1 * 0 + xx2 * 5 + xx3 * 7 + xx4 * 9 + xx5 * 13 + xx6 * 15 + xx7 * 17 + xx8 * 19 + xx9 * 21; let resto := ((sumP + sumD) / 26 - floor((sumP + sumD) / 26)) * 26; let finalC := switch text(round(resto)) do case 0: "A" case 1: "B" case 2: "C" case 3: "D" case 4: "E" case 5: "F" case 6: "G" case 7: "H" case 8: "I" case 9: "J" case 10: "K" case 11: "L" case 12: "M" case 13: "N" case 14: "O" case 15: "P" case 16: "Q" case 17: "R" case 18: "S" case 19: "T" case 20: "U" case 21: "V" case 22: "W" case 23: "X" case 24: "Y" case 25: "Z" default: "" end; cfparz + finalC
-
I did not try to understand it all, but I can see, for example, that the computation of "finalC" can be reduced to:
let finalC := item("ABCDEFGHIJKLMNOPQRSTUVWXYZ", round(resto));
The same certainly applies to the definition of a letter to represent the month of "DataNascita".
-
Still digging into your script… This:
if length(text(day(DataNascita))) = 1 then "0" + text(day(DataNascita)) else text(day(DataNascita)) end
seems to give the same result as:
format(day(DataNascita), "00")
I tried to understand the first part of the script, but it would be easier to know the intent. Is it supposed to always produce a six letter code?
-
With what I just learned, you can use
item("ABCDEHLMPRST", number(month(DataNascita))-1)
to replace
switch text(month(DataNascita)) do case "1": "A" case "2": "B" case "3": "C" case "4": "D" case "5": "E" case "6": "H" case "7": "L" case "8": "M" case "9": "P" case "10": "R" case "11": "S" case "12": "T" default: "" end
-
Next proposal - replace
let cfparz := switch xLunCog do case 1: text(xConCog) + "XX" case 2: text(xConCog) + "X" case 3: text(xConCog) default: substring(text(xCog), 0, 3) end
by
rpad(text(xConCog), 3, "X")
which just fills up xConCog with "X"es up to a total length of 3.
I didn't fully understand the principle or the intent, maybe you can directly use
rpad(substring(text(xCog), 0, 3), 3, "X")
which might (didn't check) make xLunCog obsolete.
Same for xConNom, of course
-
One more: the whole
let a := countLetters(xCarPar, "A"); let b := countLetters(xCarPar, "B"); let c := countLetters(xCarPar, "C"); let d := countLetters(xCarPar, "D"); let e := countLetters(xCarPar, "E"); let f := countLetters(xCarPar, "F"); let g := countLetters(xCarPar, "G"); let h := countLetters(xCarPar, "H"); let i := countLetters(xCarPar, "I"); let j := countLetters(xCarPar, "J"); let k := countLetters(xCarPar, "K"); let l := countLetters(xCarPar, "L"); let m := countLetters(xCarPar, "M"); let n := countLetters(xCarPar, "N"); let o := countLetters(xCarPar, "O"); let p := countLetters(xCarPar, "P"); let q := countLetters(xCarPar, "Q"); let r := countLetters(xCarPar, "R"); let s := countLetters(xCarPar, "S"); let t := countLetters(xCarPar, "T"); let u := countLetters(xCarPar, "U"); let v := countLetters(xCarPar, "V"); let w := countLetters(xCarPar, "W"); let x := countLetters(xCarPar, "X"); let y := countLetters(xCarPar, "Y"); let z := countLetters(xCarPar, "Z"); let sumP := a * 0 + b * 1 + c * 2 + d * 3 + e * 4 + f * 5 + g * 6 + h * 7 + i * 8 + j * 9 + k * 10 + l * 11 + m * 12 + n * 13 + o * 14 + p * 15 + q * 16 + r * 17 + s * 18 + t * 19 + u * 20 + v * 21 + w * 22 + x * 23 + y * 24 + z * 25
can be replaced by
let sumP := 0; for i in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" do sumP := sumP + countLetters(xCarPar, i) * index("ABCDEFGHIJKLMNOPQRSTUVWXYZ", i) end;
and then you do something similar for the numbers
-
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));
Content aside
- Status Answered
- 2 yrs agoLast active
- 36Replies
- 541Views
-
6
Following