JS小习题-简单的数据格式转换问题

感谢小怪兽不算怪兽提出的问题。

题目

题目一:

每日定时会返回观测点ABC的数据

给出以下数据

let Data = [{
  dataName: ['Point1', 'Point2', 'Point3'],
  dataValue: ['100', '95', '70']
},{
  dataName: ['Point1', 'Point2', 'Point3'],
  dataValue: ['85', '42', '65']
},{
  dataName: ['Point1', 'Point2', 'Point3'],
  dataValue: ['99', '65', '80']
}]
/* 处理后 */
let resDate = [{
  name: 'Point1', value: ['100', '85', '99']
}, {
  name: 'Point2', value: ['95', '42', '65']
}, {
  name: 'Point3', value: ['70', '65', '80']
}]
复制代码

其中Date的数据长度不固定

请给出处理方法

题目二:

每日定时会返回观测点ABCD的数据

但是由于网路信号不稳定,部分数值在传输过程中丢失,或者乱序

丢失的数据补'0'

给出以下数据

let Data = [{
  dataName: ['Point1', 'Point2', 'Point3'],
  dataValue: ['100', '95', '70']
},{
  dataName: ['Point1', 'Point2', 'Point4'],
  dataValue: ['77', '82', '65']
},{
  dataName: ['Point3', 'Point1', 'Point2'],
  dataValue: ['95', '85', '66']
},{
  dataName: ['Point2', 'Point4'],
  dataValue: ['95', '85']
}]
/* 处理后 */
let resDate = [{
  name: 'Point1', value: ['100', '77', '85', '0']
}, {
  name: 'Point2', value: ['95', '82', '66', '95']
}, {
  name: 'Point3', value: ['70', '0', '95', '0']
}, {
  name: 'Point4', value: ['0', '65', '0', '85']
}]
复制代码

其中Date的数据长度不固定

请给出处理方法

解答

问题一:

思路

假设最终结果是 res并初始化

res=[]

首先分析数据dataName中的value转为name中的value

for(name of dataName) res.push({name})

然后将dataValue中的value按顺序push到value

for(value of dataValue) res[index].value.push(value)

index的数值需要遍历res获取,或者在存储name的时候就提前存好对应的下标,这里采用空间换时间(减少遍历次数)的办法

temp = {}

在存name的时候 顺便记录下标

同时dataValuedataName是等长的,所以只遍历一次即可

这是一个类似统计的过程,所以使用reduce进行处理

示例

function zip(arr) {
    const temp = {};
    return arr.reduce(function(res, bean) {
        for(let i in bean.dataName) {
            // res 的下标也是i,这里需要在temp中也记录一下name和i的对应关系,
            let name = bean.dataName[i];
            if(name in temp){
                // 不是第一轮,可以继续push数据了
                let _i = temp[name];
                res[_i].value.push(bean.dataValue[i])
            }else {
                // 新name 存数据 存temp
                // 这里直接使用i也是可以的,但是res.length逻辑更严谨
                temp[name] = res.length;
                // name存储并初始化value
                res.push({name, value: [bean.dataValue[i]]})
            }
        }
        return res;
    },[])
}
复制代码

分析

由于是类似二维数组的结构,这里使用循环嵌套是没有问题的,核心问题在于接下来需要再次向数组中插入数据,考虑到顺序可能会变更,尽量使用辅助手段记录一下数据顺序,若不考虑顺序变更,则直接使用下标也是没有问题的。

问题二:

思路

和问题一的区别在于

部分数值在传输过程中丢失,或者乱序

发现dataName值有不全的情况以及乱序,这时候第一遍遍历后的name值是不可信的,这里的思路是将问题拆成两步,第一步先确定name,第二步插入并修补value

示例

function zip_plus(arr) {
    const temp = {};
    return arr.reduce((res, bean, index) => {
        for(let i in bean.dataName) {
            let name = bean.dataName[i];
            if(name in temp) {
                let _i = temp[name];
                res[_i].value.push(bean.dataValue[i]);
            }else {
                temp[name] = res.length;
                let value = new Array(index).fill('0').concat(bean.dataValue[i]); // 补0用
                res.push({name, value});
            }
        }
        res.forEach((ele) => {while(ele.value.length <= index) ele.value.push('0')}) // 补0用
        return res;
    }, []);
}
复制代码

分析

对于丢失的部分采取补0的策略

所以相比原来的zip方法增加了两处补0的操作

let value = new Array(index).fill('0').push(bean.dataValue[i]);

res.forEach((ele) => {while(ele.value.length <= index) ele.value.push('0')})

一个是在声明时的补0

一个是在遍历bean.dataName/bean.dataValue后的补0

猜你喜欢

转载自juejin.im/post/7042148946537349128