无需转数组高效对比两数字对应位整数?React动画优化问询
Great question! Your current implementation works, but we can streamline the digit comparison logic by using pure mathematical operations instead of converting numbers to strings and arrays. This approach is more efficient, cleaner, and handles edge cases like carry-over/borrow (e.g., 1000 → 999 or 999 → 1000) more reliably.
Core Idea
Instead of splitting numbers into string arrays, we'll extract each digit using modulo (%) and integer division (Math.floor()), starting from the least significant digit (rightmost). We'll also track carry-over/borrow states to handle cases where digits roll over (like 9 → 0 when incrementing, or 0 → 9 when decrementing).
Refactored Code
First, let's update the checkNums function and adjust the incrementTotal method to use numeric values directly:
Parent Component
class Parent extends React.Component { state = { isCreateScenarioModalVisible: false, isExpressModalVisible: false, total: 0, truesArr: [] }; // New optimized digit comparison logic checkNums = (oldTotal, newTotal) => { const truesArr = []; let oldNum = Math.abs(oldTotal); let newNum = Math.abs(newTotal); const isIncrease = newTotal > oldTotal; // Handle sign difference (e.g., -1 → 0 or 0 → -1) if (Math.sign(oldTotal) !== Math.sign(newTotal)) { const maxLength = Math.max(oldNum.toString().length, newNum.toString().length); for (let i = 0; i < maxLength; i++) { truesArr.push(isIncrease ? false : true); oldNum = Math.floor(oldNum / 10); newNum = Math.floor(newNum / 10); } // Add/remove sign digit as needed if (newTotal < 0) truesArr.push(true); if (oldTotal < 0) truesArr.pop(); } else { // Process each digit until both numbers are reduced to 0 while (oldNum > 0 || newNum > 0) { const oldDigit = oldNum % 10; const newDigit = newNum % 10; let state = null; if (isIncrease) { // Increment case: mark digits affected by increase or carry-over state = (newDigit !== oldDigit) ? false : null; } else { // Decrement case: mark digits affected by decrease or borrow state = (newDigit !== oldDigit) ? true : null; } truesArr.push(state); oldNum = Math.floor(oldNum / 10); newNum = Math.floor(newNum / 10); } } // Reverse to match left-to-right digit order this.setState({ truesArr: truesArr.reverse() }); }; incrementTotal = (arg) => { const newTotal = this.state.total + arg; // Pass old and new numeric values directly this.checkNums(this.state.total, newTotal); this.setState({ total: newTotal }, () => { console.log(this.state.truesArr); }); setTimeout(() => { this.setState({ truesArr: [] }); }, 500); }; render() { return ( <div> <div> {this.state.total.toString().split("").map((num, i) => { return <Num key={i} num={num} color={this.state.truesArr[i]} />; })} </div> <div onClick={() => this.incrementTotal(1)}>+1</div> <div onClick={() => this.incrementTotal(-1)}>-1</div> </div> ); } } export default Parent;
Child Component (Unchanged)
class Num extends React.Component { constructor(prop) { super(prop); } render() { let className; if (this.props.color === true) { className = 'red'; } else if (this.props.color === false) { className = 'green'; } else { className = 'norm'; } return <p className={className}>{this.props.num}</p>; } } export default Num;
Key Improvements
- No String/Array Conversion: Uses pure math to extract digits, which is faster and avoids edge cases with string handling (like negative signs).
- Handles Carry/Borrow: Properly identifies all digits affected by carry-over (e.g., 999 → 1000: all three 9s and the new leading 1 get green animations) or borrow (e.g., 1000 → 999: all four digits get red animations).
- Negative Number Support: Correctly processes sign changes (e.g., 0 → -1 or -1 → 0) by adjusting the animation array for the sign digit.
- Simpler Logic: Reduces conditional complexity by focusing on whether digits changed, rather than comparing raw values directly.
Example Test Cases
1000 → 1001: Only the last digit getsfalse(green animation).1000 → 999: All four digits gettrue(red animations).999 → 1000: All three original digits plus the new leading 1 getfalse(green).0 → -1: The-and1gettrue(red).
内容的提问来源于stack exchange,提问作者Matt Croak

