js 数据组装

let str='';  //i可以为任何数
for(let i=0;i<5;i++){
  str=i;
}

//如果i=5想要组装成的数据结构为

data:[
    {
      a: str,  //此时str=0
      b: str,  //此时str=1
      c: str,  //此时str=2
    },
    {
      a: str,  //此时str=3
      b: str, //此时str=4
    },
  ]

//如果i=7想要组装成的数据结构为

data:[
    {
      a: str,  //此时str=0
      b: str,  //此时str=1
      c: str,  //此时str=2
    },
    {
      a: str,  //此时str=3
      b: str,  //此时str=4
      c: str,  //此时str=5
    },{
      a: str,  //此时str=6
    },
  ]
阅读 2.4k
4 个回答
    const data = [];
    let obj = {};
    var k = 5;
    for (let i = 0; i < k; i++) {
      obj[["a", "b", "c"][i % 3]] = i;
      if (i % 3 === 2 || i === k - 1) {
        data.push(obj);
        obj = {};
      }
    }
function getData(n, keys = [...'abc']) {
  let i = 0
  const res = Array.from({ length: n / keys.length | 0 }, () => Object.fromEntries(keys.map(k => [k, i++])))
  n %= keys.length
  if (n > 0) res.push(Object.fromEntries(keys.slice(0, n).map(k => [k, i++])))
  return res
}

getData(5)

简单好理解的 chunk 算法;

const chunk = (n) => {
    const res = [], temp = ['a', 'b', 'c'];
    for (let i = 0; i < n; i += 3) {
        const obj = {};
        res.push(obj);
        for (let j = i; j < i + 3 && j < n; j++) {
            obj[temp[j - i]] = j;
        }
    }
    return res;
}

console.log(chunk(10));
// [
//     { a: 0, b: 1, c: 2 },
//     { a: 3, b: 4, c: 5 },
//     { a: 6, b: 7, c: 8 },
//     { a: 9 }
// ]

将一个列表按一定数量进行分组的行为称为分块(区别分组),程序中一般称为 chunk。这个问题虽然不是直接的 chunk,但是形式类似,可以先 chunk 再加工。

如果自己不会写,可以利用工具,Lodash
提供了大量方便的工作用来处理数据。

方法一,用 Lodash

import _ from "lodash";

function makeChunk(count, chunkSize) {
    // _.range(n) 产生 [0, n) 的序列
    return _(_.range(count))
        // 按 chunkSize 分块
        .chunk(chunkSize)
        // 对每块进行映射,映射前是一小块数值列表,如 [0, 1, 2]
        .map(r => _.fromPairs(
            // r 就是一块,对它的元素进行映射,映射成 pair/entryy,如 ['a', 0]
            // 映射成 pair 列表之后,上面的 _.fromPairs 可以从这个列表生成对象
            r.map((v, i) => [String.fromCharCode(i + 97), v]))
        )
        .value();
}
console.log(makeChunk(11, 3));

方法二,中规中矩

这是一个中规中矩的写法。同时提供了另一种计算 key 的方法,就是提前把 key 算出来放在列表里,用的时候去取。。

function makeChunk2(count, chunkSize) {
    const keys = Array.from(Array(chunkSize), (_, i) => String.fromCharCode(i + 97));
    const result = [];
    let current;
    for (let i = 0; i < count; i++) {
        if (i % chunkSize === 0) {
            current = { [keys[0]]: i };
            result.push(current);
        } else {
            current[keys[i % chunkSize]] = i;
        }
    }
    return result;
}
console.log(makeChunk2(11, 3));

方法三,用点语法糖

function makeChunk3(count, chunkSize) {
    const result = [];
    for (let i = 0; i < count; i++) {
        (result[i / chunkSize | 0] ??= {})[String.fromCharCode(97 + i % chunkSize)] = i;
    }
    return result;
}
console.log(makeChunk3(11, 3));

i / chunkSize 得到一个浮点数,再加上 | 0 可以取整。所以这是一个取整的便捷方法。~~(i / chunkSize) 也可以,就是会多写对括号。

方法四,更进一步,用 reduce

像这种有初始值(对象、数组),需要进行定量循环的场景,比较适合用 reduce 来处理

function makeChunk4(count, chunkSize) {
    return Array(count).fill(0).reduce((result, _, i) => {
        (result[i / chunkSize | 0] ??= {})[String.fromCharCode(97 + i % chunkSize)] = i;
        return result;
    }, []);
}
console.log(makeChunk4(11, 3));

Array(n).fill(0) 只是为了填充数组,未填充的数组没办法遍历。实际循环中使用是序号 i。也可以用 [...Array(n).keys()] 直接生成序号列表,在遍历时用元素值。

参考阅读:

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题