如何使用JavaScript Array Reduce重写字符串压缩/解压算法?
Hey there! Let's figure out how to rewrite your string compression and decompression functions using JavaScript's reduce() method. I'll walk through each one step by step, mapping directly from your original loop-based code so you can see how it translates.
reduce() Your original code uses a for loop paired with a while loop to count consecutive characters. With reduce(), we can track the current character and its count using an accumulator object, building the compressed string as we go.
Here's the rewritten version:
function StringCompression(str) { if (!str) return str; // Handle empty string edge case // Use reduce to track current character, its count, and the compressed result const compressionState = str.split('').reduce((acc, char) => { if (char === acc.currentChar) { // Same character as current, increment the count return { ...acc, count: acc.count + 1 }; } else { // New character: add the previous char+count to the result, reset tracking return { currentChar: char, count: 1, result: acc.result + acc.currentChar + acc.count }; } }, { currentChar: str[0], count: 1, result: '' }); // Don't forget to append the last set of characters (they won't be added in the reduce loop) const finalCompressed = compressionState.result + compressionState.currentChar + compressionState.count; // Return original string if compression doesn't save space return finalCompressed.length >= str.length ? str : `\nCompressing string '${str}'... ${finalCompressed}`; }
Key Notes:
- The accumulator (
acc) keeps track of three things: thecurrentCharwe're counting, itscount, and theresultstring we're building. - When we hit a new character, we append the previous character and its count to the result, then reset our tracking values.
- After the
reduce()loop finishes, we have to manually add the last character and count (since the loop ends before processing that final set). - We still keep your original logic to return the uncompressed string if the compressed version is longer.
reduce() Your original decompression code loops through the string, grabbing each character and its following number, then repeating the character that many times. With reduce(), we can track the current character and build the decompressed string by checking each index's position.
Here's the rewritten version:
function StringDecompression(compString) { if (!compString) return compString; // Handle empty string edge case // Use reduce to track current character and build decompressed result const decompressionState = compString.split('').reduce((acc, char, index) => { if (index % 2 === 0) { // Even index (0, 2, 4...) is a character to repeat, store it return { ...acc, currentChar: char }; } else { // Odd index is the repeat count: add the character repeated count times to result const repeatCount = parseInt(char); return { ...acc, result: acc.result + acc.currentChar.repeat(repeatCount) }; } }, { currentChar: '', result: '' }); return `Decompressing string '${compString}'... ${decompressionState.result}\n`; }
Key Notes:
- We use the
indexparameter fromreduce()to distinguish between characters (even indices) and their repeat counts (odd indices) — this matches your original code's logic of checkingiandi+1. - Instead of a nested
forloop to repeat the character, we use JavaScript's built-inString.repeat()method for cleaner code. - The accumulator tracks the current character we need to repeat and the growing decompressed result string.
Run these tests and you'll get the same output as your original functions:
console.log(StringCompression("aabbbcccccaa")); // Output: "\nCompressing string 'aabbbcccccaa'... a2b3c5a2" console.log(StringDecompression("a2b3c5a2x4")); // Output: "Decompressing string 'a2b3c5a2x4'... aabbbcccccaaxxxx\n"
内容的提问来源于stack exchange,提问作者colin_dev256

