AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

StringMod() String Manipulation - Enhanced by PhiLho / Titan
Goto page 1, 2, 3, 4, 5  Next
 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
SKAN



Joined: 26 Dec 2005
Posts: 6264

PostPosted: Fri Mar 03, 2006 7:04 am    Post subject: StringMod() String Manipulation - Enhanced by PhiLho / Titan Reply with quote

    StringMod() was originally posted in General Chat topic Numerology .

  • PhiLho enhanced the original code & included Replace, Rot13 and Rot47
  • Titan re-wrote the function and enhanced it with Scramble, Bloat, Pattern.

    Function StringMod() extracts, excludes or replaces specified characters from the String passed on to it and returns
    the modified string. It can also flip a string (reversed order) or convert it into Rot13 and Rot47.
    Additional functionality are detailed below.

    Usage: StringMod(string, method [, param1, param2])

Quote:

    String Modification: Methods with examples

    Methods:

      Only
      Omit
      Flip
      Replace
      Rot13
      Rot47
      Scramble
      Bloat
      Pattern

    Examples:

    Extract the Vowels from the name "Goyyah"
    StringMod("Goyyah","Only","AEIOU") returns "oa"

    Extract the Consonants from the name "Goyyah"
    StringMod("Goyyah","Omit","AEIOU") returns "Gyyh"

    Flips "Goyyah"
    StringMod("Goyyah","Flip") returns "hayyoG"

    Replace "*^" in "^H*e*l*l*o^" with "_"
    StringMod("^H*e*l*l*o^", "Replace" , "*^" , "_") returns "_H_e_l_l_o_"

      Example for Validating a String into Filename
    Code:
    filename = This?Is?\A:/<"Valid"File>*Name?.txt
    invalidFilenameCharacters=\/:*?"<>|
    Msgbox, % StringMod(filename, "Replace", invalidFilenameCharacters)
    ; This_Is_A___Valid_File__Name_.txt


    Convert "HELLO" into Rot13
    StringMod("Hello", "Rot13") returns "UYRRB"

    Convert "HELLO" into Rot47
    StringMod("Hello", "Rot47") returns "wt{{~"

    Scramble the word "AUTOHOTKEY"
    StringMod("AUTOHOTKEY","Scramble") will return something like "UKOTTOEAHY"

    • Laszlo's CharPerm() - similar functionality - optimised


    Stuff Characters before and after each character in the word "Autohotkey"
    StringMod("AutoHotkey","Bloat", "{" , "}" ) returns "{A}{u}{t}{o}{H}{o}{t}{k}{e}{y}"



    Pattern may be used to find the Anagrammatical relationship between two words.
    Pattern returns a String arranged in alphabetical order in such
    a way that
    the number of occurences follows each letter

      Pattern1 := StringMod("RACE","Pattern") ; "A1C1E1R1"
      Pattern2 := StringMod("CARE","Pattern") ; "A1C1E1R1"
      If Pattern1 = %Pattern2%
      ; evaluates to a logical true because both Pattern1 and Pattern2 share the same pattern "A1C1E1R1"







_________________


Last edited by SKAN on Mon Jun 16, 2008 1:09 pm; edited 17 times in total
Back to top
View user's profile Send private message
SKAN



Joined: 26 Dec 2005
Posts: 6264

PostPosted: Fri Mar 03, 2006 8:31 am    Post subject: Reply with quote

Other String Manipulation Functions

StringSlice() : Added 2006-March-19.

Quote:
StringSlice() : Similar to AHK's StringSplit Command - However, with one difference.
String is Split, based on defined width rather than a delimiter

    Example: StringSlice("Dictionary", 3, "Var") will initialise 5 Variables: Var0 through Var4

    Var0 will contain 4
    Var1 will contain "Dic"
    Var2 will contain "tio"
    Var3 will contain "nar"
    Var4 will contain "y"

Regards, Smile
_________________


Last edited by SKAN on Sun Mar 19, 2006 12:24 pm; edited 5 times in total
Back to top
View user's profile Send private message
PhiLho



Joined: 27 Dec 2005
Posts: 6721
Location: France (near Paris)

PostPosted: Fri Mar 03, 2006 10:39 am    Post subject: Reply with quote

Thanks for the credit Smile
For consistency, I would have integrated Flip into the loop:
Code:
   Loop Parse, _string
   {
      If (_mode = "Flip")
      {
         rStr := A_LoopField rStr
      }
      ; Is char in the given list?
      Else IfInString _chars, %A_LoopField%
      {
         If (_mode = "Only")
            rStr := rStr A_LoopField
         Else If (_mode = "Replace")
            rStr := rStr _replCh
      }
      Else
      {
         If (_mode = "Omit" or _mode = "Replace")
            rStr := rStr A_LoopField
      }
   }

Also I believe that the Flip code you gave may give bad results if the string has spaces (in default mode).
Such Flip function is probably not of huge utility, except perhaps to perform some AHK functions that doesn't provide a facility starting from the right of the string.
_________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")
Back to top
View user's profile Send private message Visit poster's website
PhiLho



Joined: 27 Dec 2005
Posts: 6721
Location: France (near Paris)

PostPosted: Fri Mar 03, 2006 11:21 am    Post subject: Reply with quote

Another transformation: Rot13, Rot47 and variants.
File can be downloaded from AutoHotkey.net.
Code:
StringMod(_string, _mode="", _chars="", _replCh="")
{
   local rStr, char, ascii, o

   ; Defaults
   If _mode not in Omit,Only,Replace,Flip,Rot13,Rot47
      _mode = Omit
   If _chars =
   {
      If _mode = Rot13
         _chars = 13
      Else If _mode = Rot47
         _chars = 47
      Else
         _chars = %A_Space%
   }
   If _replCh =
      _replCh = _

   Loop Parse, _string
   {
      If (_mode = "Flip")
      {
         rStr := A_LoopField rStr
      }
      Else If (_mode = "Rot13")
      {
         char := Asc(A_LoopField)
         ; o is 'A' code if it is an uppercase letter, and 'a' code if it is a lowercase letter
         o := Asc("A") * (Asc("A") <= char && char <= Asc("Z")) + Asc("a") * (Asc("a") <= char && char <= Asc("z"))
         If (o > 0)
         {
            ; Set between 0 and 25, add rotation factor, modulus alphabet size
            char := Mod(char - o + _chars, 26)
            ; Transform back to char, upper or lower
            char := Chr(char + o)
         }
         Else
         {
            ; Non alphabetic, unchanged
            char := A_LoopField
         }
         rStr := rStr char
      }
      Else If (_mode = "Rot47")
      {
         char := A_LoopField
         If char between ! and ~
         {
            char := Asc(A_LoopField)
            ; Set between 0 and 93, add rotation factor, modulus range size
            char := Mod(char - 33 + _chars, 94)
            ; Transform back to char
            char := Chr(char + 33)
         }
         rStr := rStr char
      }
      ; Is char in the given list?
      Else IfInString _chars, %A_LoopField%
      {
         If (_mode = "Only")
            rStr := rStr A_LoopField
         Else If (_mode = "Replace")
            rStr := rStr _replCh
      }
      Else
      {
         If (_mode = "Omit" or _mode = "Replace")
            rStr := rStr A_LoopField
      }
   }
   Return rStr
}

; Run test code only if the file is ran standalone
If (A_ScriptName = "StringMod.ahk")
{

str = The name of the variable whose contents will be analyzed.
filename = This?Is?\A:/<"Valid"File>*Name?.txt
invalidFilenameCharacters=\/:*?"<>|
r = |
r := r StringMod(str, "OMIT", " ") "|`n|"
r := r StringMod(str, "Omit", "aeiouy") "|`n|"
r := r StringMod(str, "only", " ") "|`n|"
r := r StringMod(str, "Only", "aeiouy ") "|`n"
r := r StringMod(str, "RePlAcE", " ") "|`n|"
r := r StringMod(str, "Replace", "aeiouy", "$") "|`n|"
r := r StringMod(str, "Flip") "|`n|"
r := r StringMod(str, "Rot13") "|`n|"
r := r StringMod(str, "Rot13", 11) "|`n|"
r := r StringMod(str, "Rot47") "|`n|"
r := r StringMod(str, "Rot47", 33) "|`n|"
r := r StringMod(filename, "Omit", invalidFilenameCharacters) "|`n|"
r := r StringMod(filename, "Replace", invalidFilenameCharacters) "|`n|"
r := r StringMod(filename, "Replace", invalidFilenameCharacters, " Fun ") "|`n"
MsgBox %r%
a1 := StringMod(str, "Rot13")
b1 := StringMod(a1, "Rot13")
a2 := StringMod(str, "Rot13", 7)
b2 := StringMod(a2, "Rot13", 26-7)
MsgBox Rot13:`n%str%`n%a1%`n%b1%`n%a2%`n%b2%
a1 := StringMod(str, "Rot47")
b1 := StringMod(a1, "Rot47")
a2 := StringMod(str, "Rot47", 13)
b2 := StringMod(a2, "Rot47", 94-13)
MsgBox Rot47:`n%str%`n%a1%`n%b1%`n%a2%`n%b2%

}

_________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")


Last edited by PhiLho on Sat Mar 04, 2006 3:09 pm; edited 3 times in total
Back to top
View user's profile Send private message Visit poster's website
Laszlo



Joined: 14 Feb 2005
Posts: 4078
Location: Pittsburgh

PostPosted: Fri Mar 03, 2006 3:34 pm    Post subject: Reply with quote

Nice functions!
…you could save a few lines at setting "o", with Shimanov's trick
Code:
o := 65*(64<char && char<91)+97*(96<char && char<123)
Back to top
View user's profile Send private message
PhiLho



Joined: 27 Dec 2005
Posts: 6721
Location: France (near Paris)

PostPosted: Fri Mar 03, 2006 4:12 pm    Post subject: Reply with quote

Thanks!
I like the If char between 65 and 87 as it was quite readable.
But I like the logic behind the expression, and using Asc calls, it is self-documenting (more or less!). And since this function is growing, saving some lines isn't too bad.
It is perhaps a bit slower, calling Asc 6 times on each loop, but I doubt it is noticeable, we rarely Rot13 whole books...
_________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")
Back to top
View user's profile Send private message Visit poster's website
SKAN



Joined: 26 Dec 2005
Posts: 6264

PostPosted: Fri Mar 03, 2006 7:50 pm    Post subject: Reply with quote

Dear PhiLho, Smile

Rot13, Rot47 and variants: Shocked I admit that I never knew about it, Thanks for Info + Function


You wrote:
For consistency, I would have integrated Flip into the loop:


I have in my mind of adding more functionality to StringMod() like

StringMod(String,"Upper")
StringMod(String,"Lower")
StringMod(String,"Title")
or StringMod(String,"Proper")


which does not require the string parsing loop & so I thought FLIP may stay out of the parsing loop.

More functionality can be added, like

StringMod(String,"OnlyDigits") ; _chars should be assigned 0123456789
StringMod(String,"A2Z") ; _chars should be assigned ABCDEFGHIJKLMNOPQRSTUVWXYZ

Instead of the present way

StringMod(String,"Only","0123456789")
StringMod(String,"Only","ABCDEFGHIJKLMNOPQRSTUVWXYZ"


Also, I am thinking about consolidating independent AHK string commands into a few but powerful functions like
writing one single function StringGet() for
StringGet(String,"Right",1)
StringGet(String,"Left",1)
StringGet(String,"Middle",10,1)

etc.

You wrote:
Flip function is probably not of huge utility, except perhaps to perform some AHK functions that doesn't provide a facility starting from the right of the string


Yes! I agree Flip is a fancy option, but maybe it will be useful for those writing word based games in AHK ( like me Wink).

Regards, Smile
Note: If anybody interested in Anagram/Jumbled word finder let me know. I've written a function for it
_________________
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 4078
Location: Pittsburgh

PostPosted: Fri Mar 03, 2006 8:25 pm    Post subject: Reply with quote

Goyyah wrote:
StringGet(String,"Right",1)
StringGet(String,"Left",1)
StringGet(String,"Middle",10,1)
You could even save the second parameter. Specify the start and end character index, where a negative index should mean counting from the end. If you call it with 2 parameters, StringGet(String,3) = StringGet(String,1,3), that is, "3 chars from Left"; or StringGet(String,-2) = StringGet(String,-2,-1), that is, "2 chars from Right". I used these in the list manipulation library.
Back to top
View user's profile Send private message
SKAN



Joined: 26 Dec 2005
Posts: 6264

PostPosted: Fri Mar 03, 2006 8:55 pm    Post subject: Reply with quote

Dear Laszlo, Smile

Offtopic: I just visited List manipulation functions. I am yet to get comfortable with Listview but your functions will be of a great help to me!

You wrote:
You could even save the second parameter. Specify the start and end character index, where a negative index should mean counting from the end.If you call it with 2 parameters,
StringGet(String,3) = StringGet(String,1,3), that is, "3 chars from Left"; or
StringGet(String,-2) = StringGet(String,-2,-1), that is, "2 chars from Right".
I used these in the list manipulation library.


Thats a good idea!. What do you suggest for StringMid()

Regards, Smile
_________________
Back to top
View user's profile Send private message
Titan



Joined: 11 Aug 2004
Posts: 5382
Location: /b/

PostPosted: Fri Mar 03, 2006 9:26 pm    Post subject: Reply with quote

Nice funciton Smile
Here is my improved rewrite - it works slightly faster, is smaller in code size and supports character rotation of n, Flip, Omit, Replace and Only (the first few lines is for demonstration):
Code:
str = The name of the variable whose contents will be analyzed.
r := "Flip:`t" . StringMod(str, "Flip") . "`nOmit "" "":`t"
   . StringMod(str, "Omit", " ")   . "`nRot13:`t" . StringMod(str, "Rot13")
   . "`nRot47:`t" . StringMod(str, "Rot47") . "`nOnly ..:`t" . StringMod(str, "only", "aeiou")
MsgBox, 64, StringMod(), Original:`t%str%`n`n%r%

StringMod(s, m="", ch="", rc="") { ; enhanced by Titan :)
   xAT := A_AutoTrim
   AutoTrim, Off
   IfEqual, ch, , SetEnv, ch, %A_Space%
   IfEqual, rc, , SetEnv, rc, _
   Loop Parse, s
      If InStr(m, "Rot") {
         StringReplace, n, m, Rot
         l := Asc(A_LoopField)
         Loop, 2 {
            If (A_Index = 1) {
               f = 65
               c = 90
            } Else {
               f = 97
               c = 122
            } If (l >= f and l <= c) {
               l += n
               Loop
                  If (l > c)
                     l := l - c + f - 1
                  Else
                     Break
            } }
            e := e . Chr(l)
      } Else If m =Flip
         e =%A_LoopField%%e%
      Else
         If InStr(ch, A_LoopField) {
            If m =Only
               e =%e%%A_LoopField%
            Else If m =Replace
               e = %e%%rc%
         } Else If m !=Only
               e =%e%%A_LoopField%
   Autotrim, % xAT
   Return, e
}


Edit: updated rotation algorithm
_________________



Last edited by Titan on Sat Mar 04, 2006 12:50 pm; edited 1 time in total
Back to top
View user's profile Send private message Visit poster's website
SKAN



Joined: 26 Dec 2005
Posts: 6264

PostPosted: Fri Mar 03, 2006 9:54 pm    Post subject: Reply with quote

Dear Titan

Great work!
_________________
Back to top
View user's profile Send private message
SKAN



Joined: 26 Dec 2005
Posts: 6264

PostPosted: Fri Mar 03, 2006 10:00 pm    Post subject: Reply with quote

Every String in my Original Code has been modified Question Exclamation except for the function name StringMod()

Regards Very Happy Very Happy Very Happy
_________________
Back to top
View user's profile Send private message
Titan



Joined: 11 Aug 2004
Posts: 5382
Location: /b/

PostPosted: Fri Mar 03, 2006 10:31 pm    Post subject: Reply with quote

Goyyah wrote:
Every String in my Original Code has been modified Question Exclamation except for the function name StringMod()
Yep, it was a complete rewrite Smile thanks for the credit.
Btw. that smilie icon is awesome Very Happy
_________________

Back to top
View user's profile Send private message Visit poster's website
SKAN



Joined: 26 Dec 2005
Posts: 6264

PostPosted: Sat Mar 04, 2006 12:17 pm    Post subject: Reply with quote

Dear Titan,

StringMod("HELLO","Rot13")

should return "URYYB"

whereas

it returns "URYY\"

Please clarify..

Also, I want to put a link for a downloadable .AHK in the first post,
so please host it and provide me a link to the same.

Regards, Smile

Edit: Titan updated his code
_________________


Last edited by SKAN on Sat Mar 04, 2006 1:10 pm; edited 1 time in total
Back to top
View user's profile Send private message
PhiLho



Joined: 27 Dec 2005
Posts: 6721
Location: France (near Paris)

PostPosted: Sat Mar 04, 2006 12:38 pm    Post subject: Reply with quote

Well, Titan's code is short and al, but it doesn't do true Rot13, which acts only on alphabetic characters and replaces them only by alphabetic chars...
So it won't decode Rot13-encoded secret messages given on Usenet (or elsewhere).
_________________
vPhiLho := RegExReplace("Philippe Lhoste", "^(\w{3})\w*\s+\b(\w{3})\w*$", "$1$2")
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page 1, 2, 3, 4, 5  Next
Page 1 of 5

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group