diff --git a/README.md b/README.md
index 0ecc224..976d094 100644
--- a/README.md
+++ b/README.md
@@ -81,6 +81,7 @@ const count = stringzy.analyze.wordCount('Hello world'); // 2
- [numberToText](#numbertotext) - Converts a number to its text representation in specified language
- [reverseWordsInString](#reversewordsinstring) - Reverses the order of words in a given string
- [stringPermutations](#stringpermutations) - Generates all unique permutations of a given string.
+- [stringCombinations](#stringcombinations) - Generates all unique combinations of a given string.
### Validations
@@ -539,6 +540,36 @@ stringPermutations('a1!');
| --------- | ------ | -------- | ----------------------------------------------------- |
| str | string | required | The input string to generate all unique permutations. |
+#### stringCombinations(str)
+
+Generates all unique combinations (subsequences) of a given string, including the empty string.
+Duplicate characters are handled by ensuring only unique combinations are returned.
+The order of combinations in the output array is not guaranteed.
+
+```javascript
+stringCombinations('ab');
+// ["", "a", "b", "ab"]
+
+stringCombinations('abc');
+// ["", "a", "b", "c", "ab", "ac", "bc", "abc"]
+
+stringCombinations('aab');
+// ["", "a", "b", "aa", "ab", "aab"]
+
+stringCombinations('');
+// [""]
+
+stringCombinations('A');
+// ["", "A"]
+
+stringCombinations('!@');
+// ["", "!", "@", "!@"]
+```
+
+| Parameter | Type | Default | Description |
+| --------- | ------ | -------- | ------------------------------------------------------ |
+| str | string | required | The input string to generate unique combinations from. |
+
### ✅ Validations
diff --git a/src/tests/transformations/stringCombinations.test.ts b/src/tests/transformations/stringCombinations.test.ts
new file mode 100644
index 0000000..0d4449f
--- /dev/null
+++ b/src/tests/transformations/stringCombinations.test.ts
@@ -0,0 +1,44 @@
+import { describe, it } from 'node:test';
+import assert from 'node:assert';
+import { stringCombinations } from '../../transformations/stringCombinations';
+
+describe('stringCombinations', () => {
+ it('returns correct combinations for 2 characters', () => {
+ const expected = ['', 'a', 'b', 'ab'];
+ assert.deepStrictEqual(stringCombinations('ab').sort(), expected.sort());
+ });
+
+ it('returns correct combinations for 3 unique characters', () => {
+ const expected = ['', 'a', 'b', 'c', 'ab', 'ac', 'bc', 'abc'];
+ assert.deepStrictEqual(stringCombinations('abc').sort(), expected.sort());
+ });
+
+ it('handles repeated characters correctly', () => {
+ const expected = ['', 'a', 'b', 'aa', 'ab', 'aab'];
+ assert.deepStrictEqual(stringCombinations('aab').sort(), expected.sort());
+ });
+
+ it('returns only empty string for empty input', () => {
+ assert.deepStrictEqual(stringCombinations(''), ['']);
+ });
+
+ it('handles single character input', () => {
+ assert.deepStrictEqual(stringCombinations('a'), ['', 'a']);
+ });
+
+ it('is case-sensitive', () => {
+ const expected = ['', 'A', 'b', 'Ab'];
+ assert.deepStrictEqual(stringCombinations('Ab').sort(), expected.sort());
+ });
+
+ it('handles special characters correctly', () => {
+ const expected = ['', '!', '@', '!@'];
+ assert.deepStrictEqual(stringCombinations('!@').sort(), expected.sort());
+ });
+
+ it('throws an error if input is not a string', () => {
+ assert.throws(() => stringCombinations(123 as any), /Input must be a string/);
+ assert.throws(() => stringCombinations(null as any), /Input must be a string/);
+ assert.throws(() => stringCombinations(undefined as any), /Input must be a string/);
+ });
+});
diff --git a/src/transformations/index.ts b/src/transformations/index.ts
index b7b322b..311c538 100644
--- a/src/transformations/index.ts
+++ b/src/transformations/index.ts
@@ -16,6 +16,7 @@ export { maskSegment } from './maskSegment';
export { numberToText } from './numberToText/main';
export { reverseWordsInString } from './reverseWordsInString ';
export { stringPermutations } from './stringPermutations';
+export { stringCombinations } from './stringCombinations';
import { camelCase } from './camelCase';
import { capitalizeWords } from './capitalizeWords';
@@ -36,6 +37,7 @@ import { deburr } from './deburr';
import { numberToText } from './numberToText/main';
import { reverseWordsInString } from './reverseWordsInString ';
import { stringPermutations } from './stringPermutations';
+import { stringCombinations } from './stringCombinations';
export const transformations = {
camelCase,
@@ -56,5 +58,6 @@ export const transformations = {
deburr,
numberToText,
reverseWordsInString,
- stringPermutations
+ stringPermutations,
+ stringCombinations
};
diff --git a/src/transformations/stringCombinations.ts b/src/transformations/stringCombinations.ts
new file mode 100644
index 0000000..2a0564b
--- /dev/null
+++ b/src/transformations/stringCombinations.ts
@@ -0,0 +1,44 @@
+/**
+ * Generates all unique combinations (subsequences) of a given string,
+ * including the empty string.
+ *
+ * Handles duplicate characters by ensuring only unique combinations are returned.
+ * The order of combinations in the output array is not guaranteed.
+ *
+ * @param {string} str - The input string to generate combinations from.
+ * @returns {string[]} An array containing all unique combinations of the string.
+ * @throws {TypeError} If the input is not a string.
+ *
+ * @example
+ * stringCombinations("ab");
+ * // ["", "a", "b", "ab"]
+ *
+ * @example
+ * stringCombinations("abc");
+ * // ["", "a", "b", "c", "ab", "ac", "bc", "abc"]
+ *
+ * @example
+ * stringCombinations("aab");
+ * // ["", "a", "b", "aa", "ab", "aab"]
+ *
+ * @example
+ * stringCombinations("");
+ * // [""]
+ */
+export function stringCombinations(str: string): string[] {
+ if (typeof str !== 'string') {
+ throw new TypeError('Input must be a string');
+ }
+
+ const results = new Set();
+
+ function backtrack(start: number, path: string) {
+ results.add(path);
+ for (let i = start; i < str.length; i++) {
+ backtrack(i + 1, path + str[i]);
+ }
+ }
+
+ backtrack(0, '');
+ return Array.from(results);
+}