感谢小怪兽不算怪兽提出的问题。
题目
题目一:
每日定时会返回观测点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的时候 顺便记录下标
同时dataValue
与dataName
是等长的,所以只遍历一次即可
这是一个类似统计的过程,所以使用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