Code: Select all
a := "cc aa bb"
b := "zz cc aa ee bb dd ff"
MsgBox % RemoveDuplicate(a " " b, " ")
;{ RemoveDuplicate
; Fanatic Guru
; 2013 05 17
;
; FUNCTION to Remove Duplicate Elements from a String with Lots of Options
;
;------------------------------------------------
;
; Method:
; RemoveDuplicate(string, delim, opt, dupe)
;
; Parameters:
; 1) {string} string to search and remove duplicates from
; 2) {delim} a series of delimiters to be used seperated by |
; delimiters can be more than one character
; delim of "" causes each single character to be parsed with no delimiters
; a | can be used as a delimiter by escaping ie. `|
; number of delimiters limited to 11, can be increased in function
; optional, default = "`n"
; 3) {opt} a combination of a number and single characters
; {number} = the number of same duplicates to keep
; F = keep First duplicate elements in string
; L = keep Last duplicate elements in string
; N = keep None of the duplicate elements in string
; S = case Sensitive
; I = case Insensitive
; E = Empty elements in string are ignored and not removed
; C = only consider Consecutive elements as duplicate
; optional, default = "1FS"
; 4) {dupe} only remove duplicate elements that match dupe
; multipy dupe can be seperated by |
; optional, default = ""
;
; Returns:
; String with duplicates removed per options
;
; Example:
; RemoveDuplicate(string,"`n|===|`||End","2SLEC","Cat|Dog|6")
;
RemoveDuplicate(string,delim:="`n",opt:="1FS",dupe:="")
{
IfInString, opt, S ; Case Sensitive
Opt_CS := true
else
Opt_CS := false
IfInString, opt, I ; Case Insensitive
Opt_CS := false
else
Opt_CS := true
IfInString, opt, F ; Keep First Duplicate
Opt_Last := false
else
Opt_Last := true
IfInString, opt, L ; Keep Last Duplicate
Opt_Last := true
else
Opt_Last := false
IfInString, opt, E ; Ignore Empty Elements and do not remove them
Opt_Empty := true
else
Opt_Empty := false
IfInString, opt, C ; Only Save Consecutive Elements are Duplicates
Opt_Con := true
else
Opt_Con := false
Position := RegExMatch(opt,"P)[0-9]+",Length)
if position
Opt_Number := SubStr(opt, Position, Length) ; Number of Duplicates to keep
else
Opt_Number := 1 ; If no numbers are given, not even zero, then default to 1
IfInString, opt, N ; Keep None of the Duplicates
Opt_Number :=0
if delim
{
delimSymbols := "§¢¤¥©ª«®µ£¬¶" ; String must not contain these symbols, add more to increase # of delim allowed
delim := RegExReplace(delim, "([^``])\|", "$1¦") ; change delimiter used in delim internally to "¦"
StringSplit, delim_array, delim, "¦"
if !(delim_array0 * 2 -1 >= StrLen(delim)) ; determine if delim contains multi-character delimiters
{
delim_multi := true
Loop, %delim_array0% ; replace actual delimiters with symbol delimiters if multi-character
{
temp_delim := delim_array%A_Index%
temp_delim_symbol := SubStr(delimSymbols,A_Index,1)
string := RegExReplace(string, "\Q" temp_delim "\E", temp_delim_symbol)
delim_parse .= temp_delim_symbol
}
}
else
{
StringReplace, delim_parse, delim,¦,,All ; use delimiters as normal if single character
}
}
if Opt_Last ; if last dupicates to be saved reverse string
{
rev_str := ""
if delim ; if delim then reverse elements
{
string := string . "¶" ; delimiter added to end for when reversing to first element
delim_parse .= "¶"
Position := 0
loop, parse, String, %delim_parse%
{
Position += StrLen(A_LoopField) + 1
rev_str := A_LoopField . SubStr(String, Position, 1) . rev_str
}
}
else ; if no delim then reverse single characters
{
VarSetCapacity(rev_str, n:=StrLen(string))
Loop %n%
rev_str .= SubStr(string, n--, 1)
}
string := rev_str
}
str := ""
oList := {}
CS := ComObjCreate("Scripting.Dictionary") ; Com Objects have case sensitive names unlike regular variables
Position := 0
Loop, parse, String, %delim_parse%
{
Position += StrLen(A_LoopField) + 1
if delim
current_delim := SubStr(String, Position, 1)
if dupe
{
if (Opt_CS and !(RegExMatch(dupe,"(^|\|)" A_LoopField "($|\|)")))
{
str .= A_LoopField current_delim
Last_Element := A_LoopField
continue
}
if (!Opt_CS and !(RegExMatch(dupe,"i)(^|\|)" A_LoopField "($|\|)")))
{
str .= A_LoopField current_delim
Last_Element := A_LoopField
continue
}
}
if Opt_Con
{
if Opt_CS
{
if (Last_Element == A_LoopField)
Con_Count += 1
else
Con_Count := 0
}
else
{
if (Last_Element = A_LoopField)
Con_Count += 1
else
Con_Count := 0
}
Last_Element := A_LoopField
if (Opt_Empty and !A_LoopField)
{
str .= A_LoopField current_delim
}
else
{
if (Opt_Number > Con_Count)
{
str .= A_LoopField current_delim
continue
}
else
{
continue
}
}
}
if (A_LoopField != "") ; element is not empty / null ie. not two delimiters together
{
if Opt_CS
{
if !CS.item(A_LoopField)
{
CS.item(A_LoopField) := 1
str .= A_LoopField current_delim
}
else
{
if !Opt_Number
{
Dupe_Position := RegExMatch(str, "P)\Q" A_LoopField "\E", Dupe_Length)
if Dupe_Position
{
if (StrLen(str) > Dupe_Position+Dupe_Length+1)
str := SubStr(str, 1, Dupe_Position-1) . SubStr(str,Dupe_Position+Dupe_Length+1)
else
str := SubStr(str, 1, Dupe_Position-1)
}
}
else
{
if (CS.item(A_LoopField) < Opt_Number)
{
CS.item(A_LoopField) += 1
str .= A_LoopField current_delim
}
}
}
}
else
{
if !oList[A_LoopField]
{
oList[A_LoopField] := 1
str .= A_LoopField current_delim
}
else
{
if !Opt_Number
{
Dupe_Position := RegExMatch(str, "P)\Q" A_LoopField "\E", Dupe_Length)
if Dupe_Position
{
if (StrLen(str) > Dupe_Position+Dupe_Length+1)
str := SubStr(str, 1, Dupe_Position-1) . SubStr(str,Dupe_Position+Dupe_Length+1)
else
str := SubStr(str, 1, Dupe_Position-1)
}
}
else
{
If (oList[A_LoopField] < Opt_Number)
{
oList[A_LoopField] += 1
str .= A_LoopField current_delim
}
}
}
}
}
else ; process empty / null element where two delimiters are together
{
if !Empty_Count
{
if !Opt_Empty
Empty_Count := 1
str .= A_LoopField current_delim
}
else
{
if !Opt_Number
{
if !empty_str
{
Loop, parse, str, %delim_parse%
{
Empty_Position += StrLen(A_LoopField) + 1
if A_LoopField
Empty_str .= A_LoopField current_delim
}
str := Empty_str
}
}
else
{
if (Empty_Count < Opt_Number)
{
Empty_Count += 1
str .= A_LoopField current_delim
}
}
}
}
}
if Opt_Last ; if last dupicates to be saved reverse string back to original order
{
rev_str := ""
if delim
{
Position := 0
loop, parse, Str, %delim_parse%
{
Position += StrLen(A_LoopField) + 1
rev_str := A_LoopField . SubStr(Str, Position, 1) . rev_str
}
StringReplace, rev_str, rev_str, ¶,,All ; remove delimiter added to end for when reversing to first element
}
else
{
VarSetCapacity(rev_str, n:=StrLen(str))
Loop %n%
rev_str .= SubStr(str, n--, 1)
}
str := rev_str
}
if delim_multi ; if multi-character delimiters replaced with symbol delimiters
{
Loop, %delim_array0% ; replace symbol delimiters with actual delimiters to restore back to original
{
temp_delim := delim_array%A_Index%
temp_delim_symbol := SubStr(delimSymbols,A_Index,1)
StringReplace, str, str, %temp_delim_symbol%, %temp_delim%, All
}
}
return str
}
;}