Check if char is letter or digit?

I try to check if a char from a string is a letter or digit.
A reverse operator of charcode[] would also be helpful, but I can’t find a useful equivalent. So I tried several operators and ended up with this filter:

[[LIDP316]split[]] :map[<currentTiddler>compare:integer:eq[A]then[yes]else[no]]

The ouput is:

7 matches
yes
yes
yes
yes
no
no
no

It seems to work for my purpose, but is it reliable and safe or rather a random finding?
Regular expressions would also come in handy to split it into alpha and numeric parts, but I’m curious if there is another way, too.
Looking forward for your replies :slight_smile:

Your filter doesn’t recognize 0 as a number. Try this instead:

{{{ [[LIDP3016]split[]] :map[[0123456789]search:title<currentTiddler>then[yes]else[no]] }}}
1 Like

@RetRoland this is an interesting approach, as is @EricShulman’s

  • It suggests an approach I have being looking for for a long time. The ability to test the input titles meets various formats.

Of interest to me is we coufd replace all alphabetic with an A and number with an N then rejoin them, The Result would then be something like AAAANNNN for your example data. We can then test this against a predefined format like [match[AAAANNNN]] to test if the input has the same “format”.

To make this reusable we can redefine Erics [0123456789] as follows and add other sets;

\define numbers() 0123456789

  • Note I use define because this is all that is required, for literals.
\define numbers() 0123456789
\define my-format() AAAANNNN

{{{ [[LIDP3016]split[]] :map[<numbers>search:title<currentTiddler>then[N]else[A]] +[join[]]  +[match<my-format>then[yes]else[no]] }}}

However we can move this logic further into functions so you can test any title matches any format we define, as a literal or a name.

[[title]test.format[AAAANNN]... or [[title]test.format<customer. Code>...

In closing I will try and share back my developments. But I would point out the regular expressions could achieve similar but they require knowledge or regular expression formats.

  • This approach works on fixed length formats but padding and other methods could be used to support variable length fields.
  • For anyone in the know my use of A, N (or 0) and also X belies experience with Cobol.
1 Like

I have taken this further as a Proof on Concept, however it can be improved for readability;

\define numbers() 0123456789
\define my-format() AAAANNNN
\define other-format() NNNNAAAA
\define alpha() abcdefghijklmnopqrstuvwxyz
\function string.title() [!is[blank]]
\function number.format() [<numbers>search:title<string.title>then[N]else<string.title>]
\function alpha.format() [<alpha>search:title<string.title>then[A]else<string.title>]
\function decompose.strings() [alpha.format[]number. Format[]] 

{{{ [[LIDP3016]split[]] :map[decompose.strings[]] +[join[]match<my-format>]   }}}

{{{ [[3016LIDP]split[]] :map[decompose.strings[]] +[join[]match<other-format>]   }}}

It only returns a result if the input matches the format.

Thank you Eric for pointing this out - I didn’t notice it.
Replaced it and experimented further, which led to a (possible) solution for me.

Filter numeric part:

{{{ [[LIDP316]split[]] :filter[[0123456789]search:title<currentTiddler>then<currentTiddler>] +[join[]] }}}

316

Get command/mnemonic:

{{{ [[LIDP316]split[]] :filter[[LIDP]search:title<currentTiddler>then<currentTiddler>] +[join[]] }}}

LIDP

Number of bytes in memory:

{{{ [[LIDP316]split[]] :filter[[0123456789]search:title<currentTiddler>then<currentTiddler>] +[split[]first[]] }}

Machine code for mnemonic:

{{{ [[LIDP316]split[]] :filter[[0123456789]search:title<currentTiddler>then<currentTiddler>] +[split[]rest[]] +[join[]]}}}

16

Really elegant @TW_Tones - this would also come in handy for me.
I will try if I can use it for variable length formats, too.
My mnemonics varying from two to five chars in length, byte code is also from 0…255.
RegEx are a possible solution, too, but it is hard to read and I’m almost sure that I don’t understand my RegEx no more some weeks later :sweat_smile:
So if there is a solution with TW-filters, then I prefer it (for now).

I also tried your POC and it worked for me, very good example!
May I note that there’s a little typo in function ‘decompose.strings’ - it should be number.format[]

Thank you very much for your extensive and informative input.

2 Likes

Likewise, But on the bright side, if you use regex your comment writing will slowly improve out of neccesity lol

Just adding to my own notes above I can see value having the opposite to a format string where you give a value and it returns a string with the found format. This can then be used as a template against which to compare other strings.

  • in the long run it may also allow us to use the template to decompose a string, for example xxxxnnnn given abcd0456 would return 'abcd 0456and you could use the first and last operator to extract one or the other, perhaps even a subtemplateNNNN`.