列表的第二例合并成一行数据的问题?

打印出的数据格式
image.png

代码如下:

var resultData = {
    listData: []
}
samplesList.forEach(function (item) {
    item.gaugingTableList.forEach((resultList) => {
        resultData.listData.push({
          caseName: item.caseName,
          factorName: resultList.factorName,
          methodNo: resultList.methodNo
      })
    })
})

渲染出来的数据是这样的
image.png

如下是需求的效果图
image.png

大佬们有没有办法列表的第二例合并成一行数据呢, 还有第三列,这两列相同的值过滤掉,只展示一个值,用原生js实现,而不是es6语法,如果用了es6语法,系统会提示错误

阅读 2.1k
2 个回答

因为你截图不是很完整,我猜测 item.caseName 是样品编号,resultList.factorName 是元素,resultList.methodNo 是检测依据
看你的图片应该是 一个样品编号对应多个检测依据,一个样品编号一个检测依据对应多个检测元素

var resultData = {
    listData: []
}
samplesList.forEach(function (item) {
    const methodNoMap = {} // 维护一个map存放这一个样品编号中检测依据和元素的关系
    const arr = []
    item.gaugingTableList.forEach((resultList) => {
        if (methodNoMap[resultList.methodNo]) {
            methodNoMap[resultList.methodNo].push(resultList.factorName)
        } else {
            methodNoMap[resultList.methodNo] = [resultList.factorName]
        }
    })
    resultData.listData.push({
        caseName: item.caseName,
        mapping: methodNoMap, // 检测依据对应的元素数组,可以直接循环
        length: Object.keys(methodNoMap).length // 一个样品编号对应的检测依据数量
    })
})

表格渲染

<table>
...
<tbody>
    <template v-for="item in resultData.listData">
        <template v-for="(value, index) in item.mapping">
            <tr>
                <td v-if="index === Object.keys(item.mapping)[0]" rowspan="item.length"></td>
                <td>{{ value.join(',') }}</td>
                <td>{{ index }}</td>
            </tr>
        </template>
    </template>
    <tr v-for=""></tr>
</tbody>
</table>

因为你没有数据,所以我随机模拟了一个(模拟数据,用的新语法,这个没关系)

const caseNames = [...Array(3).keys()].map(i => `CASE${i}`);
const names = "铜Cu,硫S,硅Si,镍Ni,铬Cr".split(",");
const methods = "GB/T 20125-2006,GB/T 11170-2008,YB/T 4396-2014".split(",");

const data = Array.from(
    { length: 30 },
    () => ({
        caseName: caseNames[~~(caseNames.length * Math.random())],
        factorName: names[~~(names.length * Math.random())],
        methodNo: methods[~~(methods.length * Math.random())],
    })
);

console.dir(data, { depth: null });

然后看要求,其实就是要 factorName 和 methodName 去重后的生成一个列表而已,所以

const nameList = [...new Set(data.map(it => it.factorName))].join(", ");
const methodList = [...new Set(data.map(it => it.methodNo))].join(", ");

下面是某一次输出的 nameList 和 methodList(看起来随机数据没生成含“硫”的)

硅Si, 铜Cu, 铬Cr, 镍Ni
GB/T 11170-2008, YB/T 4396-2014, GB/T 20125-2006

现在再加入 caseName 这个因素,猜测大概是要根据 caseName 分组合并。所以这里需要一个分组算法。因为不能用新语法,所以写起来会啰嗦,不如直接用 Lodash 处理

const result = _(data)
    // 先按 caseName 分组
    .groupBy("caseName")
    .mapValues(function (its) {
        // 分组结果是对象,键是 caseName,值是元素列表
        // 从元素列表分别取 factorName 和 methodNo,去重后拼接成字符串
        // 处理后的结果是把元素列表聚合计算成了 { factorName, methodNo }
        return {
            factorName: _(its).map(function (it) { return it.factorName; }).uniq().join(", "),
            methodNo: _(its).map(function (it) { return it.methodNo; }).uniq().join(", ")
        };
    })
    // 将分组结果变成键值对 [key, value] 的数组
    .entries()
    // 再映射成对象
    .map(function (pair) {
        return {
            caseName: pair[0],
            factorName: pair[1].factorName,
            methodNo: pair[1].methodNo
        };
    })
    // 延迟计算取值
    .value();

下面这是一个结果示例

[
  {
    caseName: 'CASE1',
    factorName: '硫S, 硅Si, 镍Ni, 铜Cu',
    methodNo: 'GB/T 11170-2008, YB/T 4396-2014'
  },
  {
    caseName: 'CASE2',
    factorName: '镍Ni, 硫S, 硅Si',
    methodNo: 'GB/T 20125-2006, YB/T 4396-2014, GB/T 11170-2008'
  },
  {
    caseName: 'CASE0',
    factorName: '铜Cu, 硫S, 硅Si, 铬Cr, 镍Ni',
    methodNo: 'GB/T 20125-2006, YB/T 4396-2014, GB/T 11170-2008'
  }
]
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题