数组的循环队列与优先队列相关问题

 let arr  = [
    {typeEum: 'gold', name: 'goldA'},
    {typeEum: 'normal', name: 'normalY'},
    {typeEum: 'normal', name: 'normalX'},
    {typeEum: 'normal', name: 'normalP'},
    {typeEum: 'normal', name: 'normalR'},
    {typeEum: 'gold', name: 'goldB'},
    {typeEum: 'gold', name: 'goldC'},
    {typeEum: 'gold', name: 'goldD'}
  ]

如果需要实现一个函数方法:在数组arr中,需要按顺序循环,每次返回3条数据,(先返回的数据,在第二次调用方法时,追加到数组末尾....大概意思就是要让数组在不断循环, 每次都返回3条数据),但是有个条件:每次返回的3条数据中的第一条数据的 typeEum 的值必须是‘gold’(即每次返回的数据第一条{typeEum: 'gold', name: ....})。
在网上看了关于javascript队列,优先队列与循环队列的文章然后捣鼓了一番,但没有达到理想效果,想请教下大神们,如果想要实现这样的一个函数方法, 有什么好的实现方式

阅读 1.4k
2 个回答

第一条是type=gold到底什么意思?每次都返回第一个条type=gold及随后的两条数据吗?还是返回的第一条是type=gold,然后从0开始再顺序找两条?
还是先搞清楚需求吧,我觉得现在这个是你针对需求自己想出来的解决思路,感觉思路本身欠缺逻辑,不如换个角度重新考虑一个方案。

已参与了 SegmentFault 思否社区 10 周年「问答」打卡 ,欢迎正在阅读的你也加入。

你这是「随机获取数组中不重复的对象并返回」这个问题的改进版问题哇 😎

其实你的思路都已经在那里了,应该可以写得出来啊,为啥不把你自己的代码贴出来给大家分析下问题呢?

这个问题基本思路是采用循环队列,JS 的数组虽然实现的队列功能,但没实现循环队列功能,可以加一个指针(序号)来解决循环的问题。然后要解决第 2 个问题,就是第一项必须是 typeEnum: "gold",那这个也需要特殊处理,就是从当前位置按顺序向后查找,找到之后把它和当前这个交换,然后按顺序取 3 个就好。

// 因为要保存状态(改变过的数组,以前指针位置),写一个 creator 函数,
// 用它来创建一个用来取数据的函数 next()
function createChooser(source) {
    const data = [...source];       // 因为有交换操作会改变原数组,所以做个副本
    const dataCount = data.length;  // 取个总数经常要用,免得每次都去取
    let position = 0;               // 当前位置,每次都从这个位置开始

    return function next(count = 3) {
        // 先从 position 找到第一个 gold 的位置
        for (let i = 0; i < dataCount; i++) {
            const current = (position + i) % dataCount;
            if (data[current].typeEum === "gold") {
                // 找到了,交换过来,然后结束循环
                [data[current], data[position]] = [data[position], data[current]];
                break;
            }
        }

        // 然后顺序取 count 个
        const result = Array.from(
            { length: count },
            (_, i) => data[(position + i) % dataCount]
        );
        position = (position + count) % dataCount;
        return result;
    };
}

const next = createChooser(arr);
for (let i = 0; i < 5; i++) {
    console.log(next());
}


// 另外实现一个把数据往后移的,效率要低一些,但应该是你的想法
// 这个直接改原数组了,懒得去写 creator 了
function choose(data, count) {
    for (let i = 0; i < data.length; i++) {
        if (data[i].typeEum === "gold") {
            [data[i], data[0]] = [data[0], data[i]];
            break;
        }
    }

    const result = data.splice(0, count);
    data.push(...result);
    return result;
}

// 测试
for (let i = 0; i < 5; i++) {
    console.log(choose(arr, 3));
}

已参与了 SegmentFault 思否社区 10 周年「问答」打卡 ,欢迎正在阅读的你也加入。
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏