diff --git a/Conversions/SnakeToCamelCase.js b/Conversions/SnakeToCamelCase.js new file mode 100644 index 0000000000..edc2a3114b --- /dev/null +++ b/Conversions/SnakeToCamelCase.js @@ -0,0 +1,44 @@ +/** + * Converts a string from snake_case to camelCase. + * + * @param {string} str - The input string in snake_case format. + * @throws {Error} Will throw an error if the input is not a string. + * @returns {string} The converted string in camelCase format. + * + * @example + * + * snakeToCamelCase("hello_world"); // Returns "helloWorld" + * snakeToCamelCase("snake_case_example"); // Returns "snakeCaseExample" + * snakeToCamelCase("_leading_underscore"); // Returns "leadingUnderscore" + * snakeToCamelCase("trailing_underscore_"); // Returns "trailingUnderscore" + * snakeToCamelCase("__multiple__underscores__"); // Returns "multipleUnderscores" + * snakeToCamelCase("snake_case@example"); // Returns "snakeCaseExample" + * snakeToCamelCase("_leading_underscore_#"); // Returns "leadingUnderscore" + * snakeToCamelCase("trailing_underscore_&"); // Returns "trailingUnderscore" + * snakeToCamelCase(""); // Returns "" + * + * @throws {Error} If the input is not a string. + */ +function snakeToCamelCase(str) { + // Will throw an error if the input is not a string. + if (typeof str !== 'string') { + throw new Error(`Expected string as input, found ${typeof str}`) + } + + if (str.trim() === '') return '' // Handle empty string + + // Remove special characters (excluding underscores) + const cleanedStr = str.replace(/[^a-zA-Z0-9_]/g, '') + + return cleanedStr + .split('_') + .filter(Boolean) + .map((value, index) => { + return index === 0 + ? value + : value.charAt(0).toUpperCase() + value.slice(1) + }) + .join('') +} + +export { snakeToCamelCase } diff --git a/Conversions/test/SnakeToCamelCase.test.js b/Conversions/test/SnakeToCamelCase.test.js new file mode 100644 index 0000000000..27e27c8203 --- /dev/null +++ b/Conversions/test/SnakeToCamelCase.test.js @@ -0,0 +1,21 @@ +import { snakeToCamelCase } from '../SnakeToCamelCase' + +describe('snakeToCamelCase', () => { + it.each([ + ['hello_world', 'helloWorld'], + ['snake_case_example', 'snakeCaseExample'], + ['_leading_underscore', 'leadingUnderscore'], + ['trailing_underscore_', 'trailingUnderscore'], + ['__multiple__underscores__', 'multipleUnderscores'], + ['snake_case@example', 'snakeCaseexample'], + ['_leading_underscore_#', 'leadingUnderscore'], + ['trailing_underscore_&', 'trailingUnderscore'], + ['', ''] + ])('converts %s to snake_case %s', (input, expected) => { + expect(snakeToCamelCase(input)).toBe(expected) + }) + + it('throws an error when the input is not a string', () => { + expect(() => snakeToCamelCase(123)).toThrow('Expected string as input') + }) +}) diff --git a/DIRECTORY.md b/DIRECTORY.md index 6c1fa7aeb8..d763bba207 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -35,6 +35,8 @@ * [ROT13](Ciphers/ROT13.js) * [VigenereCipher](Ciphers/VigenereCipher.js) * [XORCipher](Ciphers/XORCipher.js) +* **Compression** + * [RLE](Compression/RLE.js) * **Conversions** * [ArbitraryBase](Conversions/ArbitraryBase.js) * [ArrayBufferToBase64](Conversions/ArrayBufferToBase64.js) @@ -62,6 +64,7 @@ * [RgbHsvConversion](Conversions/RgbHsvConversion.js) * [RGBToHex](Conversions/RGBToHex.js) * [RomanToDecimal](Conversions/RomanToDecimal.js) + * [SnakeToCamelCase](Conversions/SnakeToCamelCase.js) * [TemperatureConversion](Conversions/TemperatureConversion.js) * [TitleCaseConversion](Conversions/TitleCaseConversion.js) * [UpperCaseConversion](Conversions/UpperCaseConversion.js) @@ -285,6 +288,7 @@ * [Problem016](Project-Euler/Problem016.js) * [Problem017](Project-Euler/Problem017.js) * [Problem018](Project-Euler/Problem018.js) + * [Problem019](Project-Euler/Problem019.js) * [Problem020](Project-Euler/Problem020.js) * [Problem021](Project-Euler/Problem021.js) * [Problem023](Project-Euler/Problem023.js)