You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

按条件splice数组元素后如何恢复原数组?(月度排班场景)

解决方案:保留原数组的每日随机选取逻辑

你的核心问题是每次循环都直接修改了原数组dutyUserArray,导致后续天数的选取基于被修改后的数组,而非原始数组。最优的解决思路是:每天基于原数组创建一个临时过滤后的副本,完全不修改原数组,这样既满足当天的条件排除需求,又能保证次日使用原始数组。

优化后的代码实现

function generateRandomSchedule(month) {
    if(!month) {
        month = localStorage.getItem('currentDutyMonth');
    }
    const monthNumber = moment().month(month).format('M');
    const year = localStorage.getItem('currentYear');
    const daysInMonth = moment(`${year}-${monthNumber}`, 'YYYY-MM').daysInMonth();

    // 提前保存原始数组的拷贝,确保每次循环都基于原始数据
    const originalDutyUsers = [...dutyUserArray];

    for(let i=1; i<daysInMonth+1; i++) {
        let date = `${moment(i, 'D').format('DD')}.${monthNumber}.`;
        const keys = Object.keys(localStorage).filter(key => key.includes(date) && !key.startsWith(month));
        
        // 收集当天需要排除的用户
        const excludedUsers = [];
        keys.forEach((key) => {
            const keyValue = localStorage.getItem(key);
            // 合并Urlaub和Spaet的判断逻辑,减少重复代码
            if((key.includes('Urlaub') || key.includes('Spaet')) && originalDutyUsers.includes(keyValue)) {
                excludedUsers.push(keyValue);
            }
        });

        // 生成当天可用的用户列表(基于原始数组过滤)
        const availableUsers = originalDutyUsers.filter(user => !excludedUsers.includes(user));
        
        // 从可用列表中随机选取
        const randomName = availableUsers[Math.floor(Math.random() * availableUsers.length)];
        
        const objectId = document.getElementById(`tdMa${date}`);
        objectId.value = randomName;

        localStorage.setItem(`${month}_tdMa${date}`, randomName);
    }
}

关键修改说明

  1. 保存原始数组:用const originalDutyUsers = [...dutyUserArray];创建原始数组的浅拷贝,确保后续所有循环都基于这份未修改的原始数据。
  2. 收集排除用户:不再直接修改原数组,而是先把当天需要排除的用户收集到excludedUsers数组中,避免破坏原数组结构。
  3. 过滤生成可用列表:通过filter方法从原始数组中排除掉当天不能选的用户,得到仅当天可用的临时数组,所有操作都不影响原数组。
  4. 简化重复逻辑:合并了Urlaub和Spaet的判断条件,减少冗余代码,提升可读性。

备选方案:临时修改后恢复原数组(不推荐)

如果一定要通过修改原数组再恢复的方式实现,可以记录每次splice的元素和索引,在当天逻辑执行完后倒序恢复(因为splice会改变数组索引,倒序插入才能保证位置正确):

function generateRandomSchedule(month) {
    if(!month) {
        month = localStorage.getItem('currentDutyMonth');
    }
    const monthNumber = moment().month(month).format('M');
    const year = localStorage.getItem('currentYear');
    const daysInMonth = moment(`${year}-${monthNumber}`, 'YYYY-MM').daysInMonth();

    for(let i=1; i<daysInMonth+1; i++) {
        let date = `${moment(i, 'D').format('DD')}.${monthNumber}.`;
        const keys = Object.keys(localStorage).filter(key => key.includes(date) && !key.startsWith(month));
        
        // 记录被移除的元素和索引
        const removedItems = [];
        keys.forEach((key) => {
            const keyValue = localStorage.getItem(key);
            if(key.includes('Urlaub') && dutyUserArray.includes(keyValue)) {
                const index = dutyUserArray.indexOf(keyValue);
                if(index > -1) {
                    removedItems.push({ index, value: dutyUserArray.splice(index, 1)[0] });
                }
            }
            if(key.includes('Spaet') && dutyUserArray.includes(keyValue)) {
                const index = dutyUserArray.indexOf(keyValue);
                if (index > -1) {
                    removedItems.push({ index, value: dutyUserArray.splice(index, 1)[0] });
                }
            }
        });

        const randomName = dutyUserArray[Math.floor(Math.random() * dutyUserArray.length)];
        const objectId = document.getElementById(`tdMa${date}`);
        objectId.value = randomName;

        localStorage.setItem(`${month}_tdMa${date}`, randomName);

        // 倒序恢复原数组,避免索引混乱
        removedItems.reverse().forEach(item => {
            dutyUserArray.splice(item.index, 0, item.value);
        });
    }
}

这种方案需要额外维护移除记录,逻辑更复杂,出错概率更高,因此优先推荐第一种基于数组过滤的方案。

内容的提问来源于stack exchange,提问作者Phil-Absynth

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 05:33:15