如何根据前一个元素的值更新数组后续元素的progress属性
The Problem
You need to update the progress property of elements in an array based on specific status conditions, but using map alone doesn't let you track prior elements' states correctly to set lock appropriately.
The Approach
Instead of trying to map status directly to progress, first identify which single element should have progress: 'start' based on your rules, then set all other elements to lock. This makes the logic straightforward and avoids confusion from overlapping status conditions.
Code Implementation
function updateProgress(array) { let activeIndex = -1; // Rule 1: All elements have status 'not_started' const allNotStarted = array.every(item => item.status === 'not_started'); if (allNotStarted) { activeIndex = 0; } // Rule 3: First two elements are 'completed' (check this before Rule 2!) else if (array[0]?.status === 'completed' && array[1]?.status === 'completed') { activeIndex = 2; } // Rule 2: First element is 'completed' else if (array[0]?.status === 'completed') { activeIndex = 1; } // Update progress for each element return array.map((item, index) => ({ ...item, // Preserve original properties progress: index === activeIndex ? 'start' : 'lock' })); }
How It Works
- Determine the active index:
- First check if all elements are
not_started→ activate the first element (index 0). - Next, check if the first two elements are both
completed→ activate the third element (index 2). We check this before Rule 2 because Rule 3's condition includes Rule 2's condition. - Then check if just the first element is
completed→ activate the second element (index 1).
- First check if all elements are
- Update the array:
- Use
mapto iterate over the array. For each element, if its index matches the active index, setprogress: 'start'; otherwise, setprogress: 'lock'. - The spread operator (
...item) ensures we keep all original properties (likenameandstatus) while only updatingprogress.
- Use
Test Examples
// Test Rule 1: All not_started let myArray = [ {name: "Sam", status: 'not_started', progress: 'start'}, {name: "Sara", status: 'not_started', progress: 'start'}, {name: "John", status: 'not_started', progress: 'start'}, {name: "Eric", status: 'not_started', progress: 'start'} ]; console.log(updateProgress(myArray)); // Output: Sam has 'start', others have 'lock' // Test Rule 2: First element completed let array2 = [ {name: "Sam", status: 'completed', progress: 'done'}, {name: "Sara", status: 'not_started', progress: 'start'}, {name: "John", status: 'not_started', progress: 'start'}, {name: "Eric", status: 'not_started', progress: 'start'} ]; console.log(updateProgress(array2)); // Output: Sara has 'start', others have 'lock' // Test Rule 3: First two completed let array3 = [ {name: "Sam", status: 'completed', progress: 'done'}, {name: "Sara", status: 'completed', progress: 'done'}, {name: "John", status: 'not_started', progress: 'start'}, {name: "Eric", status: 'not_started', progress: 'start'} ]; console.log(updateProgress(array3)); // Output: John has 'start', others have 'lock'
Why This Beats Your Initial Map Approach
Your original map attempt struggled because it treated each element in isolation. By first identifying the single active element, we eliminate ambiguity—there's no question whether a not_started element should be start or lock because we already know exactly which one gets the special treatment.
内容的提问来源于stack exchange,提问作者User7354632781

