Programming Language Comparison: Strings

Strings Mathematics Operators and Symbols [string interpolation] General (Control Flow/Debugging) [multi-line strings] Dates Objects [Array.Join/Array.ToString, Array.Print/Map.Print] New Features Timelines Note: UFL: Universal Function Library, a set of around 100-300 standard functions for all programming languages. Languages do not have to implement anything exactly to the UFL specification, it is a guide. See lower down for further details. UFL: String [(or ToString): ValueToString, sometimes also ObjToString/ObjectToString][note: oArrayAny indicates worked on Int/Float/String array, oArrayStr indicates worked on String array only] AutoHotkey: String [e.g. String(vNum)] C++: ___ [can use: std::to_string(vNum)] C#: ___ [can use: vNum.ToString()][also: String.Join(vSep, oArrayAny)] Excel: TEXT [e.g. TEXT(A1,"General")][also: =""&A1] Excel VBA: CStr [e.g. CStr(vNum)][also: Join(oArrayAny, vSep)] Java: ___ [can use (for numbers): String.valueOf(vNum), Integer.toString(vNum), Double.toString(vNum), "" + vNum][also: java.util.Arrays.toString(oArrayAny)][also: String.join(vSep, oArrayStr)] JavaScript: String [e.g. String(vNum)][e.g. String(oArrayAny)][also: oArrayAny.join(vSep)] Kotlin: ___ [can use: vNum.toString()][also: oArrayAny.joinToString(vSep)][also: oArrayAny.toList().toString()] PHP: strval [e.g. strval($vNum)][also: implode($vSep, $oArrayAny)][also: var_export($oArrayAny, true)] Python: str [e.g. str(vNum)][e.g. str(oArrayAny)][also: vSep.join(oArrayStr)][also: vSep.join(map(str, oArrayAny))] Swift: String [e.g. String(vNum)][also: oArrayAny.description][e.g. String(describing:oArrayAny)][e.g. String(reflecting:oArrayAny)][also: oArrayStr.joined(separator:vSep)] UFL: CharToStr [FIXME][char type to string type] AutoHotkey: ___ C++: ___ C#: ___ Excel: ___ Excel VBA: ___ Java: ___ [also: String.valueOf(vChar)][also: Character.toString(vChar)][can use: "" + vChar] JavaScript: ___ Kotlin: ___ PHP: ___ Python: ___ Swift: ___ UFL: StrToChar [FIXME][get first char][string type to char type] AutoHotkey: ___ C++: ___ C#: ___ Excel: ___ Excel VBA: ___ Java: ___ JavaScript: ___ Kotlin: ___ PHP: ___ Python: ___ Swift: ___ UFL: StrLower/StrUpper AutoHotkey: StrLower/StrUpper [e.g. StrLower(vText)] C++: tolower/toupper [e.g. (modifies string): transform(vText.begin(), vText.end(), vText.begin(), ::tolower)] C#: ToLower/ToUpper [e.g. vText.ToLower()] Excel: LOWER/UPPER [e.g. LOWER(A1)] Excel VBA: LCase/UCase [also: StrConv][e.g. LCase(vText)] Java: toLowerCase/toUpperCase [e.g. vText.toLowerCase()] JavaScript: toLowerCase/toUpperCase [e.g. vText.toLowerCase()] Kotlin: lowercase/uppercase [e.g. vText.lowercase()][deprecated: toLowerCase/toUpperCase] PHP: strtolower/strtoupper [e.g. strtolower(vText)] Python: str.lower/str.upper [e.g. vText.lower()] Swift: lowercased/uppercased [e.g. vText.lowercased()] UFL: StrTitle [set all words to title case] AutoHotkey: StrTitle C++: ___ C#: ___ Excel: PROPER Excel VBA: WorksheetFunction.Proper [also: StrConv with vbProperCase] Java: ___ JavaScript: ___ Kotlin: ___ PHP: ___ Python: str.title Swift: ___ UFL: StrCompare AutoHotkey: StrCompare [WARNING: case insensitive by default][e.g. StrCompare(vText1, vText2)][note (since AHK v2): < > can't compare strings] C++: compare [e.g. vTextA.compare(vTextB)][also: <=>][can use: < >][also: memcmp/strcmp/strncmp/wcscmp/wcsncmp] C#: String.Compare [e.g. String.Compare(vTextA, vTextB)][note: < > can't compare strings] Excel: ___ [can use: < >] Excel VBA: StrComp [e.g. StrComp(vTextA, vTextB)][can use: < >] Java: compareTo [e.g. vTextA.compareTo(vTextB)][also: compareToIgnoreCase][note: < > can't compare strings] JavaScript: ___ [can use: < >] Kotlin: compareTo [e.g. vTextA.compareTo(vTextB)][can use: < >] PHP: substr_compare [WARNING: case insensitive by default][e.g. substr_compare($vTextA, $vTextB, 0, null, true)][can use: < >] Python: ___ [can use: < >] Swift: ___ [can use: < >] UFL: StrEquals AutoHotkey: ___ C++: ___ C#: Equals Excel: EXACT Excel VBA: ___ Java: equals [also: equalsIgnoreCase] JavaScript: ___ Kotlin: equals PHP: ___ Python: operator.eq Swift: elementsEqual UFL: (StrBetween)/(StrBetweenUntil) [StrBetween: inclusive to inclusive, StrBetweenUntil: inclusive to exclusive] AutoHotkey: ___/___ C++: ___/___ C#: ___/___ Excel: ___/___ Excel ___/___ Java: ___/___ JavaScript: ___/___ Kotlin: ___/___ PHP: ___/___ Python: ___/___ Swift: ___/___ UFL: Chr [codepoint to character (as string)] AutoHotkey: Chr [e.g. (codepoints 0-1114111): Chr(vOrd)] C++: ___ [e.g. (ASCII: codepoints 0-127): std::string vChar{(char)vOrd}][e.g. treble clef: std::string vChar{(char)240,(char)157,(char)132,(char)158}][note: std::string stores strings as bytes (UTF-8)] C#: ConvertFromUtf32 [e.g. (codepoints 0-1114111): Char.ConvertFromUtf32(vOrd)] Excel: UNICHAR [e.g. (codepoints 0-1114111): UNICHAR(A1)][note: UNICHAR (Excel 2013)][WARNING: CHAR only handles codepoints 0-127 (ASCII) reliably] Excel VBA: ChrW [e.g. (codepoints 0-65535): ChrW(vOrd)][e.g. treble clef: ChrW(55348) & ChrW(56606)] Java: ___ [can use (codepoints 0-1114111): new String(new int[]{vOrd}, 0, 1)][also (codepoints 0-65535): Character.toString(vOrd)][also: Character.toChars()][WARNING: Java chars go up to 0xFFFF (not 0xFF)] JavaScript: String.fromCodePoint [e.g. (codepoints 0-1114111): String.fromCodePoint(vOrd)][also: String.fromCharCode(), e.g. treble clef: String.fromCharCode(55348, 56606)] Kotlin: toString [e.g. (codepoints 0-1114111): Character.toString(vOrd)] PHP: mb_chr [e.g. (codepoints 0-1114111): mb_chr($vOrd)][WARNING: chr only handles codepoints 0-255] Python: chr [e.g. (codepoints 0-1114111): chr(vOrd)] Swift: ___ [can use (codepoints 0-1114111): Character(UnicodeScalar(vOrd)!)] UFL: Ord [codepoint at start of string] AutoHotkey: Ord [e.g. (codepoints 0-1114111): Ord(vText)] C++: ___ [e.g. read 1 byte: (int)(unsigned char)vText[0]][note: cast to int so that std::cout prints chars as integers not symbols][note: std::string stores strings as bytes (UTF-8)] C#: ConvertToUtf32 [e.g. (codepoints 0-1114111): Char.ConvertToUtf32(vText, 0)] Excel: UNICODE [e.g. (codepoints 0-1114111): UNICODE(A1)][note: UNICODE (Excel 2013)][WARNING: CODE only handles codepoints 0-127 (ASCII) reliably] Excel VBA: AscW [e.g. (codepoints 0-65535): AscW(vText) And 65535][WARNING: codepoints 32768-65535 return -32768 to -1, i.e. a signed short (Int16) rather than an unsigned short (UInt16), use 'And 65535' (bitwise and) to fix this (to correct negative return values and leave positive values unchanged)] Java: codePointAt [e.g. (codepoints 0-1114111): vText.codePointAt(0)] JavaScript: codePointAt [e.g. (codepoints 0-1114111): vText.codePointAt()][also (codepoints 0-65535): vText.charCodeAt()] Kotlin: codePointAt [e.g. (codepoints 0-1114111): vText.codePointAt(0)][also (codepoints 0-65535): vText.single().code][deprecated: vText.toInt()] PHP: mb_ord [e.g. (codepoints 0-1114111): mb_ord(vText)][WARNING: ord only handles codepoints 0-255] Python: ord [e.g. (codepoints 0-1114111): ord(vText)] Swift: ___ [can use (codepoints 0-1114111): Int(UnicodeScalar(vText).value)] UFL: ChrAt [nth character (as string) (a substring)][WARNING: 0-based/1-based position][see also: SubStr] AutoHotkey: ___ [can use (UTF-16 short, 1-based): SubStr(vText, vPos, 1)][can use (codepoint, 1-based): RegExReplace(vText, "^.{" (vPos-1) "}(.).*$", "$1")] C++: ___ [e.g. (UTF-8 byte): std::string("") + vText[vPos]] C#: ___ [e.g. (UTF-16 short): "" + vText[vPos]] Excel: ___ [can use (UTF-16 short, 1-based): MID(A1,vPos,1)] Excel VBA: ___ [can use (UTF-16 short, 1-based): Mid(vText, vPos, 1)] Java: charAt [e.g. (UTF-16 short): "" + vText.charAt(vPos)] JavaScript: ___ [can use (codepoint): [...vText][vPos]][note: 'Strings are iterated by Unicode code points.'][can use (UTF-16 short): vText.charAt(vPos)] Kotlin: get [e.g. (UTF-16 short): "" + vText.get(vPos)] PHP: ___ [can use (codepoint): mb_substr($vText, $vPos, 1)][can use (UTF-8 byte): $vText[$vPos]] Python: ___ [can use (codepoint): vText[vPos]] Swift: ___ [can use (codepoint): Array(vText)[vPos]][can use (codepoint): vText[vText.index(vText.startIndex, offsetBy:vPos)]] UFL: OrdAt [codepoint of nth character][WARNING: 0-based/1-based position] AutoHotkey: ___ [can use: Ord(SubStr(vText, vPos, 2))][WARNING: uses UTF-16 shorts, position may be partway through a char (returns low surrogate)] C++: ___ C#: ConvertToUtf32 [e.g. Char.ConvertToUtf32(vText, vPos)][WARNING: uses UTF-16 shorts, position may be partway through a char (throws)] Excel: ___ Excel VBA: ___ Java: codePointAt [e.g. vText.codePointAt(vPos)][WARNING: uses UTF-16 shorts, position may be partway through a char (returns low surrogate)] JavaScript: codePointAt [e.g. vText.codePointAt(vPos)][WARNING: uses UTF-16 shorts, position may be partway through a char (returns low surrogate)] Kotlin: codePointAt [e.g. vText.codePointAt(vPos)][WARNING: uses UTF-16 shorts, position may be partway through a char (returns low surrogate)] PHP: ___ [can use: mb_ord(mb_substr($vText, $vPos, 1))] Python: ___ [can use: ord(vText[vPos])] Swift: ___ UFL: StrRept [or StrRepeat] AutoHotkey: ___ [can use: StrReplace(Format("{:" vCount "}", ""), " ", vText)] C++: ___ [can use (to repeat a character): std::string(vCount, vChar)][can use: += repeatedly] C#: ___ [can use: String.Concat(Enumerable.Repeat(vText, vCount))][also (slower): (new String('_', vCount)).Replace("_", vText)][requires (Repeat): using System.Linq] Excel: REPT [e.g. REPT(vText,vCount)] Excel VBA: WorksheetFunction.Rept [e.g. WorksheetFunction.Rept(vText, vCount)][also: Space and Replace][also: String and Replace][also: String to repeat a character] Java: repeat [e.g. vText.repeat(vCount)] JavaScript: repeat [e.g. vText.repeat(vCount)] Kotlin: repeat [e.g. vText.repeat(vCount)] PHP: str_repeat [e.g. str_repeat($vText, $vCount)] Python: ___ [can use (* operator): vText * vCount][WARNING: mathematical operator used on strings] Swift: String [e.g. String(repeating:vText, count:vCount)] UFL: StrCount [WARNING: 0-based/1-based position] AutoHotkey: ___ C++: ___ C#: ___ Excel: ___ [can use: =(LEN(A1)-LEN(SUBSTITUTE(A1,B1,"")))/LEN(B1)][can use (for 1-char needles): =LEN(A1)-LEN(SUBSTITUTE(A1,B1,""))] Excel VBA: ___ Java: ___ JavaScript: ___ Kotlin: ___ PHP: substr_count Python: str.count Swift: ___ UFL: StrLen AutoHotkey: StrLen [e.g. StrLen(vText)][unit: UTF-16 shorts] C++: length [e.g. vText.length()][also: strlen/wcslen][unit: UTF-8 bytes] C#: Length [e.g. vText.Length][unit: UTF-16 shorts] Excel: LEN [e.g. LEN(A1)][unit: UTF-16 shorts] Excel VBA: Len [e.g. Len(vText)][unit: UTF-16 shorts] Java: length [e.g. vText.length()][unit: UTF-16 shorts][WARNING: vText.length() requires parentheses, unlike oArray.length] JavaScript: length [e.g. vText.length][unit: UTF-16 shorts] Kotlin: length [e.g. vText.length][also: vText.count()][unit: UTF-16 shorts] PHP: strlen [e.g. strlen($vText)][unit: UTF-8 bytes] Python: len [e.g. len(vText)][unit: codepoints][note: Python 2 and 3 differ] Swift: count [e.g. vText.count][unit: codepoints] UFL: StrLenDemo [square root (a BMP char), treble clef (a surrogate pair)] AutoHotkey: StrLen("√"), StrLen("𝄞") [output: 1,2][unit: UTF-16 shorts] C++: std::string("√").length(), std::string("𝄞").length() [output: 3,4][unit: UTF-8 bytes] C#: "√".Length, "𝄞".Length [output: 1,2][unit: UTF-16 shorts] Excel: √, 𝄞 [output: 1,2][unit: UTF-16 shorts] Excel VBA: Len(ChrW(8730)), Len(ChrW(55348) & ChrW(56606)) [output: 1,2][unit: UTF-16 shorts] Java: "√".length(), "𝄞".length() [output: 1,2][unit: UTF-16 shorts] JavaScript: "√".length, "𝄞".length [output: 1,2][unit: UTF-16 shorts] Kotlin: "√".length, "𝄞".length [output: 1,2][unit: UTF-16 shorts][note: vText.count(): same results] PHP: strlen("√"), strlen("𝄞") [output: 3,4][unit: UTF-8 bytes] Python: len("√"), len("𝄞") [output: 1,1][unit: codepoints] Swift: "√".count, "𝄞".count [output: 1,1][unit: codepoints] UFL: StrSizeUtf8 [size of string in bytes (UTF-8 encoded)] AutoHotkey: ___ [can use: StrPut(vText, "UTF-8")-1][note: StrPut returns the size in bytes including a null character] C++: ___ [can use: std::string(vText).length()] C#: ___ [can use: Encoding.UTF8.GetBytes(vText).Length] Excel: ___ Excel VBA: ___ Java: ___ [can use: vText.getBytes().length] JavaScript: [e.g. new TextEncoder().encode(vText).length] Kotlin: ___ [can use: vText.toByteArray().size] PHP: strlen [e.g. strlen(vText)] Python: ___ [can use: len(vText.encode("utf-8")] Swift: ___ [can use: vText.utf8.count] UFL: StrLenUtf16 [size of string in (2-byte) shorts (UTF-16 encoded)][note: double this value to get 'StrSizeUtf16', size in bytes] AutoHotkey: StrLen [e.g. StrLen(vText)] C++: ___ [can use: for (const auto& vChar : vText) vLen += ((vChar&0xC0)!=0x80) + ((vChar&0xF8)==0xF0)][beforehand: int vLen = 0][also: vLen = std::accumulate(vText.begin(), vText.end(), 0, [](int vAcc, int vChar) {return vAcc+((vChar&0xC0)!=0x80)+((vChar&0xF8)==0xF0);})][requires (std::accumulate): #include <numeric>][note: +1 if byte doesn't start with 0b10, +1 if byte doesn't start with 0b11110] C#: Length [e.g. vText.Length] Excel: LEN [e.g. LEN(A1)] Excel VBA: Len [e.g. Len(vText)] Java: length [e.g. vText.length()][WARNING: vText.length() requires parentheses, unlike oArray.length] JavaScript: length [e.g. vText.length] Kotlin: length [e.g. vText.length][also: vText.count()] PHP: ___ [can use: strlen(mb_convert_encoding($vText, "UTF-16"))/2] Python: ___ [can use: len(vText.encode("utf-16-le")/2][WARNING (encode): 'utf-16' prepends a 2-byte BOM] Swift: ___ [can use: vText.utf16.count] UFL: (StrLenCodepoints) [or StrLenUtf32][note: quadruple this value to get 'StrSizeUtf32', size in bytes] AutoHotkey: ___ [can use: RegExReplace(vText, ".",, &vLen)][note: AHK v1: drop the '&'] C++: ___ [can use: for (const auto& vChar : vText) vLen += ((vChar&0xC0)!=0x80)][beforehand: int vLen = 0][also: vLen = std::accumulate(vText.begin(), vText.end(), 0, [](int vAcc, int vChar) {return vAcc+((vChar&0xC0)!=0x80);})][requires (std::accumulate): #include <numeric>][note: +1 if byte doesn't start with 0b10] C#: ___ [can use: Encoding.UTF32.GetBytes(vText).Length/4] Excel: ___ Excel VBA: ___ Java: codePointCount [e.g. vText.codePointCount(0, vText.length())] JavaScript: ___ [can use: [...vText].length][note: 'Strings are iterated by Unicode code points.'] Kotlin: codePointCount [e.g. vText.codePointCount(0, vText.length)] PHP: ___ [can use: strlen(mb_convert_encoding($vText, "UTF-32"))/4) Python: ___ [can use: len(vText)] Swift: ___ [can use: vText.count] UFL: StrGetCapacity [get string capacity] AutoHotkey: VarSetStrCapacity [e.g. vCapacity := VarSetStrCapacity(&vText)][note: VarSetStrCapacity can *get* and set the capacity] C++: capacity [e.g. vCapacity = vText.capacity()] C#: ___ [note: StringBuilder: vCapacity = oSB.Capacity][requires: using System.Text] Excel: ___ Excel VBA: ___ Java: capacity [e.g. vCapacity = oSB.capacity()] JavaScript: ___ Kotlin: ___ [note: StringBuilder: oSB.capacity()] PHP: ___ Python: ___ Swift: ___ UFL: StrSetCapacity [set string capacity (or request a minimum capacity)] AutoHotkey: VarSetStrCapacity [e.g. VarSetStrCapacity(&vText, vCapacity)][WARNING: makes the string blank] C++: reserve [e.g. vText.reserve(vCapacity)][also: vText.shrink_to_fit()] C#: ___ [note: StringBuilder: oSB.Capacity = vCapacity][requires: using System.Text] Excel: ___ Excel VBA: ___ Java: ___ [note: StringBuilder: oSB.ensureCapacity(vCapacity)][also: StringBuilder: oSB.trimToSize()] JavaScript: ___ Kotlin: ___ [note: StringBuilder: oSB.ensureCapacity(vCapacity)][also: StringBuilder: oSB.trimToSize()] PHP: ___ Python: ___ Swift: ___ UFL: StrReplace [replace string with string (no RegEx), all occurrences, there may be an option to replace the first n occurrences][WARNING: 0-based/1-based position] AutoHotkey: StrReplace [WARNING: case insensitive by default][e.g. vTextNew := StrReplace(vText, vBefore, vAfter)] C++: ___ [can use: repeated find and replace][also (case insensitive): repeated find and std::search] C#: Replace [e.g. vTextNew = vText.Replace(vBefore, vAfter)] Excel: SUBSTITUTE [e.g. SUBSTITUTE(A1,vBefore,vAfter)] Excel VBA: Replace [e.g. vTextNew = Replace(vText, vBefore, vAfter)] Java: replace [e.g. vTextNew = vText.replace(vBefore, vAfter)] JavaScript: replaceAll [e.g. vTextNew = vText.replaceAll(vBefore, vAfter)] Kotlin: replace [e.g. vTextNew = vText.replace(vBefore, vAfter)] PHP: str_replace [e.g. $vTextNew = str_replace($vBefore, $vAfter, $vText)] Python: str.replace [e.g. vTextNew = vText.replace(vBefore, vAfter)] Swift: replacingOccurrences [e.g. vText.replacingOccurrences(of:vBefore, with:vAfter)][requires: import Foundation] UFL: StrSplit [string to array (split by delimiters)][see also: StrSplitChars][note: can accept a multi-char string as a separator unless stated] AutoHotkey: StrSplit [e.g. oArray := StrSplit(vText, vSep)][note: blank delimiter: 1 output string per char] C++: ___ [can use: repeated find and substr][also (single-char separator only): std::stringstream and getline][WARNING: getline ignores a blank line after the last separator][requires (std::stringstream): #include <sstream>] C#: Split [e.g. oArray = vText.Split(vSep)][note: blank delimiter: 1 output string (entire string)] Excel: TEXTSPLIT [note: TEXTSPLIT (Excel 365)] Excel VBA: Split [e.g. oArray = Split(vText, vSep)][note: blank delimiter: 1 output string (entire string)] Java: split [WARNING: splits based on RegEx, not a literal string][e.g. oArray = vText.split(vSep)][note: blank delimiter: 1 output string per char] JavaScript: split [e.g. oArray = vText.split(vSep)][note: blank delimiter: 1 output string per char] Kotlin: split [WARNING: blank delimiter: 1 output string per char, with 2 (leading/trailing) blank strings][e.g. oArray = vText.split(vSep).toTypedArray()] PHP: explode [WARNING: str_split splits into chunks of size n, not by delimiter][e.g. $oArray = explode($vSep, $vText)][note: blank delimiter: throws] Python: str.split [e.g. oArray = vText.split(vSep)][note: use list to split a string to a list of 1-char strings][note: str.rsplit returns the last n items if maxsplit is specified][note: blank delimiter: throws] Swift: split [e.g. oArray = vText.split(separator:vSep).map{String($0)}][note: blank delimiter: 1 output string per char] UFL: (StrSplitChars) [equivalent to StrChunk(vText, 1)][create an array of strings of length 1][note: maintain surrogate pairs unless stated][WARNING: in some languages, "".split(vSep) returns [""], not []] AutoHotkey: ___ [can use (find a char not in vText first): StrSplit(RegExReplace(vText, "(?<=.)(?=.)", vUnused), vUnused)][can use: StrSplit(vText)][also: StrSplit(vText, "")][WARNING: StrSplit no/blank separator splits surrogate pairs][note (all approaches): split blank string: return array length 0] C++: ___ C#: ___ [string[] oArray = Regex.Split(vText, "(?<=.)(?=.)(?![\uDC00-\uDFFF])")][requires (Regex.Split): using System.Text.RegularExpressions][also: StringInfo.GetTextElementEnumerator][also: UTF32Encoding and BitConverter][also (WARNING: splits surrogate pairs): string[] oArray = vText.Select(v=>v.ToString()).ToArray()][WARNING (Regex.Split): split blank string: return array length 1] Excel: ___ Excel VBA: ___ Java: ___ [can use: String[] oArray = vText.codePoints().mapToObj(Character::toString).toArray(String[]::new)][also: vText.split("(?<=.)")][can use (WARNING: splits surrogate pairs): vText.split("")][WARNING (for both approaches using 'split'): split blank string: return array length 1] JavaScript: ___ [can use: [...vText]][note: 'Strings are iterated by Unicode code points.'][note: split blank string: return array length 0][also (WARNING: splits any surrogate pairs): vText.split("")] Kotlin: ___ [can use: vText.codePoints().mapToObj{Character.toString(it)}.toList().toTypedArray()][can use (WARNING: splits surrogate pairs): vText.chunked(1)][WARNING: split("") returns blank strings at start and end][also: vText.split("").drop(1).dropLast(1)][note: chunked(): split blank string: return array length 0][note: split(): split blank string: return array length 2, which is string length + 2, consistent with non-blank strings] PHP: ___ [can use: mb_str_split($vText)][note: split blank string: return array length 0][WARNING: str_split (unlike mb_str_split) splits by bytes] Python: ___ [can use: list(vText)][note: split blank string: return array length 0] Swift: ___ [can use: Array(vText).map{String($0)}][note: split blank string: return array length 0] UFL: StrChunk [or StrSplitLen][string to array (split into chunks of n chars)] AutoHotkey: ___ C++: ___ C#: ___ Excel: ___ Excel VBA: ___ Java: ___ JavaScript: ___ Kotlin: chunked PHP: mb_str_split [WARNING: str_split (unlike mb_str_split) splits by bytes (e.g. based on their UTF-8 bytes: mb_chr(8730) becomes 3 chars, mb_chr(119070) becomes 4 chars) (mb_str_split splits based on codepoints)][WARNING: splits into chunks of size n, not by delimiter] Python: ___ Swift: ___ UFL: (StrHatch) [add a separator every n chars] AutoHotkey: ___ C++: ___ C#: ___ Excel: ___ Excel VBA: ___ Java: ___ JavaScript: ___ Kotlin: ___ PHP: chunk_split [WARNING: doesn't split to an array, adds a separator every n chars] Python: ___ Swift: ___ UFL: StrJoin [specify separator string, then one or more strings][e.g. StrJoin(vSep, oArray*)] AutoHotkey: ___ C++: ___ [can use: += repeatedly][also: note: strcat/wcscat] C#: ___ [can use: String.Join(vSep, oArray)] Excel: ___ [can use: TEXTJOIN(vSep,, vText1, vText2, vText3)][note: TEXTJOIN (Excel 2016)] Excel VBA: ___ [can use: Join(oArray, vSep)] Java: ___ [can use: String.join(vSep, oArray)][can use: String.join(vSep, vText1, vText2, vText3)] JavaScript: ___ [can use: oArray.join(vSep)] Kotlin: ___ [can use: oArray.joinToString(vSep)] PHP: ___ [can use: implode(vSep, oArray)][also (alias): join(vSep, oArray)] Python: ___ [can use: str.join, e.g. vSep.join(oArray)][WARNING: can't do: oArray.join(vSep)][note: where oArray is a list] Swift: ___ [can use: oArray.joined(separator:vSep)] UFL: StrContains AutoHotkey: InStr [note: 1-based][WARNING: case insensitive by default] C++: ___ C#: Contains Excel: ___ [can use: =IFERROR(FIND(vNeedle,A1)>0,0)][note: FIND returns #VALUE! error if fails] Excel VBA: InStr [note: 1-based] Java: contains JavaScript: includes Kotlin: contains PHP: str_contains Python: ___ Swift: contains UFL: InStr/IntStrRev [WARNING: 0-based/1-based position] AutoHotkey: InStr/InStr [note: 1-based][WARNING: case insensitive by default] C++: find/rfind [also (case insensitive, forwards or backwards): std::search][also: strstr/wcsstr] C#: IndexOf/LastIndexOf Excel: FIND/___ [can use (find last): get needle string count (LEN/SUBSTITUTE), replace last needle occurrence with temporary char (SUBSTITUTE), find char (FIND) (note: '0+' '+0' put around string count for clarity): =FIND(CHAR(1),SUBSTITUTE(A1,B1,CHAR(1),0+(LEN(A1)-LEN(SUBSTITUTE(A1,B1,"")))/LEN(B1)+0))][note: 1-based][note: FIND returns #VALUE! error if fails] Excel VBA: InStr/InStrRev [note: 1-based] Java: indexOf/lastIndexOf JavaScript: indexOf/lastIndexOf Kotlin: indexOf/lastIndexOf [note: don't confuse with indexOfLast] PHP: strpos/strrpos Python: str.find/str.rfind [note: str.index/str.rindex search but throw if fail] Swift: ___/___ UFL: StrStarts/StrEnds [see also: StrEquals/StrContains] AutoHotkey: ___/___ C++: strncmp/___ [also: wcsncmp] C#: StartsWith/EndsWith Excel: ___/___ Excel VBA: ___/___ Java: startsWith/endsWith JavaScript: startsWith/endsWith Kotlin: startsWith/endsWith PHP: str_starts_with/str_ends_with Python: str.startswith/str.endswith Swift: hasPrefix/hasSuffix UFL: RegExMatch [find offset of first match, get text of any substrings][WARNING: 0-based/1-based position] AutoHotkey: RegExMatch [can use: ~=] C++: std::regex_search [note: std::regex_match has to match the whole string] C#: Match Excel: ___ Excel VBA: ___ [can use: CreateObject("VBScript.RegExp") and Test] Java: find JavaScript: search Kotlin: find [also: containsMatchIn/contains] PHP: preg_match Python: re.search Swift: firstMatch [also: wholeMatch] UFL: (RegExMatchWhole) [has to match the whole string] AutoHotkey: ___ C++: std::regex_match [note: whole-string match] C#: ___ Excel: ___ Excel VBA: ___ Java: matches [note: whole-string match] JavaScript: ___ Kotlin: matches [e.g. "abc".matches(Regex("..."))][also: Regex("...").matchEntire("abc")][note (both): whole-string match] PHP: ___ Python: re.fullmatch Swift: wholeMatch UFL: RegExMatchAll [find all matches][WARNING: 0-based/1-based position] AutoHotkey: ___ C++: std::regex_iterator [also: repeated std::regex_search] C#: Matches Excel: ___ Excel VBA: ___ [can use: CreateObject("VBScript.RegExp") and Execute] Java: ___ [can use: find repeatedly] JavaScript: matchAll Kotlin: findAll PHP: preg_match_all Python: re.findall [also: re.split] Swift: matches UFL: RegExReplace AutoHotkey: RegExReplace C++: std::regex_replace C#: Regex.Replace Excel: ___ Excel VBA: ___ [can use: CreateObject("VBScript.RegExp") and Replace] Java: replaceAll JavaScript: replace Kotlin: replace PHP: preg_replace Python: re.sub Swift: replacingOccurrences [also: stringByReplacingMatchesInString] UFL: RegExEscape [or StrEscape][add escape characters to treat all characters literally rather than as metacharacters] AutoHotkey: ___ C++: ___ C#: Regex.Escape Excel: ___ Excel VBA: ___ Java: ___ JavaScript: ___ Kotlin: Regex.escape PHP: preg_quote Python: re.escape Swift: ___ UFL: SubStr [substring using pos/count][WARNING: 0-based/1-based position] AutoHotkey: SubStr [e.g. SubStr(vText, vPos, vCount)] C++: substr [e.g. vText.substr(vPos, vCount)] C#: Substring [e.g. vText.Substring(vPos, vCount)] Excel: MID [e.g. MID(A1,vPos,vCount)] Excel VBA: Mid [e.g. Mid(vText, vPos, vCount)][note: unlike Excel sheet function, can omit count parameter] Java: ___ [can use: vText.substring(vPos, vPos+vCount)] JavaScript: ___ [can use: vText.slice(vPos, vPos+vCount)][deprecated: substr(vPos, vCount)][note: don't confuse with substring(vPos1, vPos2)] Kotlin: ___ [can use: vText.slice(vPos..<vPos+vCount)] PHP: substr [e.g. substr($vText, $vPos, $vCount)] Python: ___ [can use: vText[vPos:vPos+vCount]] Swift: ___ [can use: String(Array(vText)[vPos..<vPos+vCount])] UFL: (StrSliceExc) [substring using pos1/pos2 (exclusive end)][WARNING: 0-based/1-based position] AutoHotkey: ___ [can use: SubStr(vText, vPos1, vPos2-vPos1)] C++: ___ [can use: vText.substr(vPos1, vPos2-vPos1)] C#: ___ [can use: vText.Substring(vPos1, vPos2-vPos1)] Excel: ___ [can use: MID(A1,vPos1,vPos2-vPos1)] Excel VBA: ___ [can use: Mid(vText, vPos1, vPos2 - vPos1)] Java: substring [e.g. vText.substring(vPos1, vPos2)][WARNING: pos1/pos2 ('substr'/'substring' is often pos/count)] JavaScript: slice [e.g. vText.slice(vPos1, vPos2)][also: substring(vPos1, vPos2)][note: don't confuse with (deprecated) substr(vPos, vCount)] Kotlin: slice [e.g. vText.slice(vPos1..<vPos2)][also: substring][deprecated: subSequence] PHP: ___ [can use: substr($vText, $vPos1, $vPos2-$vPos1)] Python: ___ [can use: vText[vPos1:vPos2]][note: vText[start:end:step]] Swift: ___ [can use: vTextNew = String(vText[vText.index(vText.startIndex, offsetBy:vPos1)..<vText.index(vText.startIndex, offsetBy:vPos2)])][also: vTextNew = String(Array(vText)[vPos1..<vPos2])][also: vTextNew = String(vText.dropFirst(vPos1).dropLast(vText.count-vPos2))] UFL: (StrSliceInc) [substring using pos1/pos2 (inclusive end)][WARNING: 0-based/1-based position] AutoHotkey: ___ [can use: SubStr(vText, vPos1, vPos2-vPos1+1)] C++: ___ [can use: vText.substr(vPos1, vPos2-vPos1+1)] C#: ___ [can use: vText.Substring(vPos1, vPos2-vPos1+1)] Excel: ___ [can use: MID(A1,vPos1,vPos2-vPos1+1)] Excel VBA: ___ [can use: Mid(vText, vPos1, vPos2 - vPos1 + 1)] Java: ___ [can use: vText.substring(vPos1, vPos2+1)][WARNING: pos1/pos2 ('substr'/'substring' is often pos/count)] JavaScript: ___ [can use: vText.slice(vPos1, vPos2+1)] Kotlin: slice [e.g. vText.slice(vPos1..vPos2)] PHP: ___ [can use: substr($vText, $vPos1, $vPos2-$vPos1+1)] Python: ___ [can use: vText[vPos1:vPos2+1]] Swift: ___ [can use: String(Array(vText)[vPos1...vPos2])] UFL: (StrLeft) [or StrTakeLeft/StrTakeFirst] AutoHotkey: ___ C++: ___ C#: ___ Excel: LEFT Excel VBA: Left Java: ___ JavaScript: ___ [can use: vText.slice(0, vCount)][also: substring] Kotlin: take PHP: ___ Python: ___ Swift: prefix UFL: (StrRight) [or StrTakeRight/StrTakeLast] AutoHotkey: ___ C++: ___ C#: ___ Excel: RIGHT Excel VBA: Right Java: ___ JavaScript: ___ [can use: vText.slice(-vCount)][also: substring] Kotlin: takeLast PHP: ___ Python: ___ Swift: suffix UFL: (StrDropLeft) [or StrDropFirst] AutoHotkey: ___ [can use: vTextNew := SubStr(vText, vCount+1)] C++: ___ [can use: vTextNew = vText.substr(vCount)] C#: ___ [can use: vTextNew = vText.Remove(0, vCount)][also: vTextNew = vText.Substring(vCount)] Excel: ___ [can use: drop left 10: =MID(A1,11,LEN(A1))][e.g. drop left 10: =REPLACE(A1,1,10,"")][e.g. drop left 10: =IFERROR(RIGHT(A1,LEN(A1)-10),"")] Excel VBA: ___ [can use: vTextNew = Mid(vText, vCount + 1)] Java: ___ [can use: vTextNew = vText.substring(vCount, vText.length())] JavaScript: ___ [can use: vTextNew = vText.slice(vCount)][also: substring] Kotlin: drop [e.g. vTextNew = vText.drop(vCount)] PHP: ___ [can use: $vTextNew = substr($vText, $vCount)] Python: ___ [can use: vTextNew = vText[vCount:]] Swift: dropFirst [e.g. vTextNew = String(vText.dropFirst(vCount))] UFL: (StrDropRight) [or StrDropLast] AutoHotkey: ___ [can use: vTextNew := SubStr(vText, 1, -vCount)] C++: ___ [can use: vTextNew = vText.substr(0, vText.length()-vCount)] C#: ___ [can use: vTextNew = vText.Remove(vText.Length-vCount)][also: vTextNew = vText.Substring(0, vText.Length-vCount)] Excel: ___ [can use: drop right 10: =IFERROR(LEFT(A1,LEN(A1)-10),"")][e.g. drop right 10: =IFERROR(MID(A1,1,LEN(A1)-10),"")] Excel VBA: ___ [can use: vTextNew = Mid(vText, 1, Len(vText) - vCount)] Java: ___ [can use: vTextNew = vText.substring(0, vText.length()-vCount)] JavaScript: ___ [can use: vTextNew = vText.slice(0, -vCount)][also: substring] Kotlin: dropLast [e.g. vTextNew = vText.dropLast(vCount)] PHP: ___ [can use: $vTextNew = substr($vText, 0, -$vCount)] Python: ___ [can use: vTextNew = vText[:-vCount]] Swift: dropLast [e.g. vTextNew = String(vText.dropLast(vCount))] UFL: (StrDropBothEnds) [or StrDropLeftAndRight/StrDropFirstAndLast][drop the first n1 chars, and the last n2 chars] AutoHotkey: ___ [can use: vTextNew := SubStr(vText, vCount1+1, -vCount2)] C++: ___ [can use: vTextNew = vText.substr(vCount1, vText.length()-vCount1-vCount2)] C#: ___ [can use: vTextNew = vText.Substring(vCount1, vText.Length-vCount1-vCount2)] Excel: ___ [can use: MID(A1,vCount1+1,LEN(A1)-vCount1-vCount2)] Excel VBA: ___ [can use: vTextNew = Mid(vText, vCount1 + 1, Len(vText) - vCount1 - vCount2)] Java: ___ [can use: vTextNew = vText.substring(vCount1, vText.length()-vCount2)] JavaScript: ___ [can use: vTextNew = vText.slice(vCount1, -vCount2)] Kotlin: ___ [can use: vTextNew = vText.drop(vCount1).dropLast(vCount2)] PHP: ___ [can use: $vTextNew = substr($vText, vCount1, -vCount2)] Python: ___ [can use: vTextNew = vText[vCount1:-vCount2]] Swift: ___ [can use: vTextNew = String(vText.dropFirst(vCount1).dropLast(vCount2))] UFL: (StrSort) [sort string based on a delimiter char] AutoHotkey: Sort [WARNING: case insensitive by default] C++: ___ C#: ___ Excel: ___ Excel VBA: ___ Java: ___ JavaScript: ___ Kotlin: ___ PHP: ___ Python: ___ Swift: ___ UFL: (StrAlphabetize) [or StrAlphabetise][alphabetise characters in string] AutoHotkey: ___ C++: std::sort C#: ___ Excel: ___ Excel VBA: ___ Java: ___ JavaScript: ___ Kotlin: ___ PHP: ___ Python: ___ Swift: ___ UFL: (StrReverse) [reverse characters in string] AutoHotkey: ___ C++: std::reverse C#: ___ Excel: ___ Excel VBA: StrReverse Java: reverse JavaScript: ___ [can use: vTextNew = [...vText].reverse().join("")][note: 'Strings are iterated by Unicode code points.'][also (WARNING: 'messes up' any surrogate pairs): vTextNew = vText.split("").reverse().join("")] Kotlin: reversed PHP: strrev Python: ___ Swift: reversed UFL: (StrShuffle) [shuffle (randomly sort) characters in string] AutoHotkey: ___ C++: std::shuffle [deprecated: std::random_shuffle] C#: ___ Excel: ___ Excel VBA: ___ Java: Collections.shuffle JavaScript: ___ Kotlin: ___ PHP: str_shuffle Python: ___ [can use: random.shuffle or random.sample] Swift: ___ UFL: Trim/LTrim/RTrim [crop chars from start/end/both (specify a custom list of chars)] AutoHotkey: Trim/LTrim/RTrim C++: ___/___/___ [can use: strspn/wcsspn to count leading chars] C#: Trim/TrimStart/TrimEnd Excel: ___/___/___ [note: TRIM only handles whitespace] Excel VBA: ___/___/___ [note: Trim/LTrim/RTrim only handle whitespace] Java: ___/___/___ [note: trim only handles whitespace] JavaScript: ___/___/___ [note: trim/trimStart/trimEnd only handle whitespace] Kotlin: trim/trimStart/trimEnd PHP: trim/ltrim/rtrim [also (alias of rtrim): chop] Python: str.strip/str.lstrip/str.rstrip Swift: ___/___/___ [note: trimmingCharacters only handles whitespace] UFL: StrDiff/(StrDiffFirst)/(StrDiffLast) [WARNING: 0-based/1-based position] AutoHotkey: ___/___/___ C++: ___/___/___ [note: memcmp/strcmp/wcscmp indicates which is greater] C#: ___/___/___ [can use: Zip/TakeWhile/Count] Excel: ___/___/___ Excel VBA: ___/___/___ Java: ___/___/___ [can use: StringUtils.difference] JavaScript: ___/___/___ Kotlin: ___/commonPrefixWith/commonSuffixWith PHP: ___/___/___ [note: can apply xor to strings e.g. strspn($vText1 ^ $vText2, "\0")] Python: ___/___/___ Swift: ___/commonPrefix/___ UFL: (Format) [produce text in a similar way to sprintf (using string interpolation): a format string and parameters] AutoHotkey: Format C++: std::format [also: sprintf/vsprintf] C#: String.Format Excel: ___ Excel VBA: ___ Java: String.format JavaScript: ___ [note: JavaScript has template strings] Kotlin: String.format PHP: sprintf Python: str.format Swift: String [note: with format options][e.g. String(format:vFormat, arguments:oArray)] UFL: (StrConcat) AutoHotkey: ___ [can use: .][can use: auto-concat] C++: strcat [also: wcscat][can use: +] C#: Concat [can use: +] Excel: CONCAT [can use: &][deprecated: CONCATENATE] Excel VBA: ___ [can use: Join][also: &][also: +] Java: concat [can use: +] JavaScript: concat [can use: +] Kotlin: plus [can use: +][deprecated: concat] PHP: ___ [can use: join/sprintf][can use: .] Python: operator.concat [can use: +] Swift: append [can use: +] UFL: StrPadLeft/StrPadRight AutoHotkey: ___/___ [can use (to left pad): Format] C++: ___/___ [can use: sprintf/vsprintf] C#: PadLeft/PadRight Excel: ___/___ [can use: TEXT] Excel VBA: ___/___ [can use: WorksheetFunction.Text] Java: ___/___ [can use: String.format] JavaScript: padStart/padEnd Kotlin: padStart/padEnd PHP: str_pad/str_pad Python: str.rjust/str.ljust [note: right/left][note: str.zfill pads leading zeros] Swift: padding/padding [also: stringByPaddingToLength] UFL: StrSpan/StrCompSpan [span / complementary span e.g. count the leading whitespace chars] AutoHotkey: ___/___ C++: strspn/strcspn [also: wcsspn/wcscspn] C#: ___/___ Excel: ___/___ Excel VBA: ___/___ Java: ___/___ JavaScript: ___/___ Kotlin: ___/___ PHP: strspn/strcspn Python: ___/___ Swift: ___/___ UFL: (StrWrap) AutoHotkey: ___ C++: ___ C#: ___ Excel: ___ Excel VBA: ___ Java: ___ JavaScript:___ Kotlin: ___ PHP: wordwrap Python: textwrap.fill Swift: ___ UFL: ChrUnused [ChrUnused(oStrings*), return a char not present in oStrings*, e.g. ChrUnused("abc", "def", "ghi") returns Chr(1)] AutoHotkey: ___ C++: ___ C#: ___ Excel: ___ Excel VBA: ___ Java: ___ JavaScript:___ Kotlin: ___ PHP: ___ Python: ___ Swift: ___ UFL: (StrToName) [or StrToFilename (e.g. webpage title to file name)] AutoHotkey: ___ C++: ___ C#: ___ Excel: ___ Excel VBA: ___ Java: ___ JavaScript:___ Kotlin: ___ PHP: ___ Python: ___ Swift: ___

The Universal Function Library Project: Details

Notes: Function names, parameter names, parameter order, and functionality recommendations, are approximate suggestions; there may be good arguments for alternatives. Function names in parentheses are regarded as somewhat or considerably lower priority. Many example functions are available at JEE.js, the function library that powers this website. Pos parameters are intended to handle one or both of: integer (StartPos) and array ([StartPos, EndPos]). Where Pos is 1-based or 0-based depending on the programming language. CaseSen parameters are case sensitive by default, but could accept a case-insensitive locale/standard. One simple case insensitive standard would only treat A-Z/a-z as case insensitive. Functions that accept or return a position, could return 0-based or 1-based positions. Such functions are labelled with '[WARNING: 0-based/1-based position]'. Author's Intro: Functions that I would like to see more widely in particular are: StrCount/StrRept (e.g. they are used in algorithms and for counting lines/URLs) StrEquals/StrContains/StrStarts/StrEnds (safer and clearer than alternatives, more convenient than creating a function every time they're needed, and would enable the easier migration of code between programming languages) And languages to have both of: SubStr (pos/length) and StrSlice (pos1/pos2) UFL: StrLower/StrUpper format: StrLower(Text, LocaleOrStandard:=unset) format: StrUpper(Text, LocaleOrStandard:=unset) demo: StrLower("ABC Abc abc") ;abc abc abc demo: StrUpper("ABC Abc abc") ;ABC ABC ABC recommendation: one simple standard would only modify chars A-Z/a-z UFL: StrTitle [set all words to title case] format: StrTitle(Text, LocaleOrStandard:=unset, Options:=unset) demo: StrTitle("ABC Abc abc") ;Abc Abc Abc recommendation: set all words to title case, some functions simply capitalise the first character recommendation: introduce one or more ISO 'title case' standards recommendation: make available information to match title case in common programs e.g. MS Word/MS Excel recommendation: options could include: only modify words that are lower case recommendation: options could include: words that should not be modified recommendation: options could include: words that should not be forcibly made lower case UFL: StrCompare/StrEquals format: StrCompare(Text1, Text2, CaseSen:=unset) [note: returns positive/0/negative] format: StrEquals(Text1, Text2, CaseSen:=unset) demo: StrCompare("abc", "def") ;-1 demo: StrEquals("abc", "def") ;False recommendation: SAFETY: while !StrCompare would be equivalent to StrEquals, for code clarity and code safety, it is worth having both recommendation: it is always worthwhile to have function versions of common operators (e.g. '==') recommendation: StrEquals(a, b, IgnoreCase) beats (a.lowercase == b.lowercase) recommendation: having StrEquals completes the set of StrEquals/StrContains/StrStarts/StrEnds UFL: (StrBetween)/(StrBetweenUntil) [between: inclusive to inclusive, until: inclusive to exclusive] format: StrBetween(Needle, Bound1, Bound2, CaseSen:=unset) format: StrBetweenUntil(Needle, Bound1, Bound2, CaseSen:=unset) demo: StrBetween("abc", "a", "abc") ;True demo: StrBetweenUntil("abc", "a", "abc") ;False demo: StrBetweenUntil("abc", "a", "b") ;True recommendation: SAFETY: for safety, it is better if < > <= >= do not compare strings, but instead throw, thus functions are wanted instead UFL: Chr [codepoint to character] format: Chr(Number, Options:=unset) demo: Chr(97) ;a recommendation: the default could be to consider codepoints, with an option to consider subunits e.g. UTF-16 2-byte 'chars' UFL: Ord [codepoint at start of string] format: Ord(Text, Options:=unset) demo: Ord("abc") ;97 recommendation: the default could be to consider codepoints, with an option to consider subunits e.g. UTF-16 2-byte 'chars' UFL: ChrAt/OrdAt [nth character/codepoint of nth character][WARNING: 0-based/1-based position] format: ChrAt(Text, Pos, Options:=unset) format: OrdAt(Text, Pos, Options:=unset) demo: ChrAt("abc", 2) ;b (1-based position) demo: OrdAt("abc", 2) ;98 (1-based position) recommendation: SAFETY: 1-based positions are safer and more intuitive (but the language may already be using 0-based positions) UFL: StrRept [or StrRepeat] format: StrRept(Text, Count) demo: StrRept("abc_", 3) ;abc_abc_abc_ recommendation: 'Rept' rather than 'Repeat', to keep the name short, it can often be used multiple times in one expression UFL: StrCount [WARNING: 0-based/1-based position] format: StrCount(Text, Needle, CaseSen:=unset, Pos:=unset) demo: StrCount("abcabcabc", "a") ;3 UFL: StrLen/(StrLenCodepoints) format: StrLen(Text, Options:=unset) demo: StrLen("abc") ;3 recommendation: the default could be to consider codepoints, with an option to consider subunits e.g. UTF-16 2-byte 'chars' UFL: StrReplace [replace string with string (no RegEx), all occurrences, there may be an option to replace the first n occurrences][WARNING: 0-based/1-based position] format: StrReplace(Text, Before, After:="", CaseSen:=unset, &Count:=unset, Limit:=unset, Pos:=unset) demo: StrReplace("abcabcabc", "b", "_",, &Count) ;a_ca_ca_ca_c (Count is 4) demo: StrReplace("abcabcabcabc", "b", "_",, &Count, 1, 7) ;abcabca_cabc (Count is 1) recommendation: if After is omitted, then replace the needle text (Before) with blank strings recommendation: a ByRef Count parameter could return the number of replacements made (alternatively an Options parameter could return [Output, Count] or just Count) recommendation: a Limit parameter could limit how many replacements are made, with no limit by default UFL: StrSplit/StrChunk/(StrHatch) [StrSplit: string to array (split by delimiters), StrChunk (or StrSplitLen): string to array (split into chunks of n chars), StrHatch: add a separator every n chars] format: StrSplit(Text, Delim:="", OmitChars:="", MaxParts:=unset) format: StrChunk(Text, Length, Options:=unset) format: StrHatch(Text, Sep, Length:=1, Options:=unset) demo: StrSplit("abc") ;[a,b,c] demo: StrSplit("a,b,c", ",") ;[a,b,c] demo: StrSplit("a|b|c", "|") ;[a,b,c] demo: StrChunk("abcdef", 2) ;[ab,cd,ef] demo: StrHatch("abcdef", "|", 2) ;ab|cd|ef recommendation: StrSplit: if Delim is blank, split into an array of 1-char strings recommendation: if MaxParts is n, return n-1 normal parts, and one 'rest of' part recommendation: Options: for StrChunk/StrHatch, this could start chunking/hatching from the right author's note: for StrHatch: 'Length' then 'Sep' might be a better fit with StrChunk author's note: I coined 'StrHatch', based on the idea of cross-hatching in drawing, adding lines at fixed intervals (but alternative names are welcome) UFL: StrJoin [specify separator string, then one or more strings][e.g. StrJoin(vSep, oValues*)] format: StrJoin(Sep, Values*) demo: StrJoin(",", ["a", "b", "c"]) ;a,b,c demo: StrJoin(["=", ","], ["k1", "v1", "k2", "v2"]) ;k1=v1,k2=v2 UFL: StrContains/InStr/IntStrRev [WARNING: 0-based/1-based position] format: StrContains(Text, Needle, CaseSen:=unset) format: InStr(Text, Needle, CaseSen:=unset, Pos:=unset, Occ:=unset) format: InStrRev(Text, Needle, CaseSen:=unset, Pos:=unset, Occ:=unset) recommendation: SAFETY: InStr/IntStrRev as separate functions simplifies the usage (search left-to-right versus right-to-left) UFL: StrStarts/StrEnds [see also: StrEquals/StrContains] format: StrStarts(Text, Needle, CaseSen:=unset) format: StrEnds(Text, Needle, CaseSen:=unset) UFL: RegExMatch [find offset of first match, get text of any substrings][WARNING: 0-based/1-based position] format: RegExMatch(Text, Needle, &Match:=unset, Pos:=unset) UFL: (RegExMatchWhole) format: RegExMatchWhole(Text, Needle, &Match:=unset, Pos:=unset) UFL: RegExMatchAll [find all matches][WARNING: 0-based/1-based position] format: RegExMatchAll(Text, Needle, Pos:=unset) UFL: RegExReplace format: RegExReplace(Text, Needle, Replacement:="", &Count:=unset, Limit:=unset, Pos:=unset) UFL: StrEscape [or RegExEscape][add escape characters to treat all characters literally rather than as metacharacters] format: StrEscape(Text, CharList:="", Options:=unset) recommendation: CharList to determine which characters to escape recommendation: options could allow RegEx escaping using '\Q' and '\E' UFL: SubStr [substring using pos/length][WARNING: 0-based/1-based position] format: SubStr(Text, Pos, Count) UFL: (StrSlice) [substring using pos1/pos2][WARNING: 0-based/1-based position] format: StrSlice(Text, Pos1, Post2) UFL: (StrLeft)/(StrRight) format: StrLeft(Text, Count) format: StrRight(Text, Count) recommendation: SAFETY: unlike other slice functions, these handily avoid using 1-based/0-based positions recommendation: if Text is shorther than Count, return the whole string UFL: (StrDropLeft)/(StrDropRight) format: StrDropLeft(Text, Count) format: StrDropRight(Text, Count) recommendation: SAFETY: unlike other slice functions, these handily avoid using 1-based/0-based positions recommendation: if Text is shorther than Count, return a blank string UFL: (StrSort) [sort string based on a delimiter char] format: Sort(Text, Options, Callback) format: Sort(Text, Callback) author's note: there are various parameter options, including having a separate Delimiter parameter UFL: (StrAlphabetize)/(StrReverse)/(StrShuffle) format: StrAlphabetize(Text) format: StrReverse(Text) format: StrShuffle(Text) UFL: Trim/LTrim/RTrim [crop chars from start/end/both] recommendation: handle any characters, not just whitespace characters format: Trim(Text, OmitChars:=" \t") format: LTrim(Text, OmitChars:=" \t") format: RTrim(Text, OmitChars:=" \t") UFL: StrDiff/(StrDiffFirst)/(StrDiffLast) [WARNING: 0-based/1-based position] format: StrDiff(Text1, Text2, CaseSen:=unset) [note: returns the position of the first difference between 2 strings] UFL: (Format) [produce text in a similar way to sprintf (using string interpolation): a format string and parameters] format: Format(FormatStr, Values*) UFL: (StrConcat) format: StrConcat(Values*) UFL: StrPadLeft/StrPadRight UFL: StrSpan/StrCompSpan [span / complementary span e.g. count the leading whitespace chars] format: JEE_StrSpan(Text, NeedleChars) format: JEE_StrCompSpan(Text, NeedleChars) UFL: (StrWrap) UFL: ChrUnused [ChrUnused(Strings*), return a char not present in Strings*] format: ChrUnused(Values*) recommendation: an Options object could give more granular control author's note: where possible, consider adding functions that reduce the need for a ChrUnused function (e.g. StrChunk) UFL: (StrToName) [or StrToFilename] format: StrToName(Title, LocaleOrStandard) author's note: e.g. for a webpage title, what file name would the web browser save it as