前言
1.多组数据长度不同,比如一组是[12,20,30],另一组是[22,32,15,45,55],这里只是举例子告诉长度不同,实际的数组是对象数组,不是这样的普通数组
2.多组数据返回时有重复值,并且不同组数据混在一起返回形成一个大数组
3.数据去重得通过两个条件,分别是名称和时间。数据里的id没什么用,名字是分组条件,时间是x轴,dataValue是值
4.数据得和时间对应,不能后端返回时9点对应值为40,图上却因为数据缺失导致10点的50对应到9点的40位置
5.没有一段代码是我自己想的(@^@)
一、后端返回值举例
1. 数据按名称分类,“测试温度描述”和“测试温度描述4”是两组数据
2. 同一组数据会有重复值,比如返回值举例里的"id:15"和"id:17",虽然id不同,但是是同一组数据且时间、数据相同
[
{
"id":7,
"sendTime":"2023-01-03 09:00:00",
"dataDetail":"测试温度描述",
"dataValue":"100",
},
{
"id":9,
"sendTime":"2023-01-03 09:10:00",
"dataDetail":"测试温度描述",
"dataValue":"100",
},
{
"id":11,
"sendTime":"2023-01-03 09:20:00",
"dataDetail":"测试温度描述",
"dataValue":"100",
},
{
"id":13,
"sendTime":"2023-01-03 09:30:00",
"dataDetail":"测试温度描述",
"dataValue":"100",
},
{
"id":15,
"sendTime":"2023-01-03 09:40:00",
"dataDetail":"测试温度描述",
"dataValue":"110",
},
{
"id":17,
"sendTime":"2023-01-03 09:40:00",
"dataDetail":"测试温度描述",
"dataValue":"110",
},
{
"id":19,
"sendTime":"2023-01-03 09:50:00",
"dataDetail":"测试温度描述",
"dataValue":"110",
},
{
"id":21,
"sendTime":"2023-01-03 10:00:00",
"dataDetail":"测试温度描述",
"dataValue":"110",
},
{
"id":25,
"sendTime":"2023-01-03 10:00:00",
"dataDetail":"测试温度描述",
"dataValue":"110",
},
{
"id":31,
"sendTime":"2023-01-03 10:00:00",
"dataDetail":"测试温度描述4",
"dataValue":"410",
},
{
"id":33,
"sendTime":"2023-01-03 10:00:00",
"dataDetail":"测试温度描述",
"dataValue":"110",
},
{
"id":39,
"devId":0,
"sendTime":"2023-01-03 10:00:00",
"dataDetail":"测试温度描述4",
"dataValue":"410",
},
{
"id":41,
"sendTime":"2023-01-03 10:10:00",
"dataDetail":"测试温度描述",
"dataValue":"110",
},
{
"id":47,
"sendTime":"2023-01-03 10:10:00",
"dataDetail":"测试温度描述4",
"dataValue":"410",
}
]
二、数据去重
1.首先将重复的数据去掉,这里要判断两次,首先是名称,其次是时间
刚开始想用filter或者some什么的函数,但是我不太会用,所以第一次修改失败,参考
失败代码:
let arrAll=arr.filter(function(item,index){
let myArr=[] // 对象的某个属性放入临时数组,对比临时数组中元素所在对象的索引,
let myArr2 = []
// 多个对象可push多个,均不相同return ..&&.. 有一不同 return ..||..
arr.forEach(item2=>{
myArr.push(item2.dataDetail)
})
arr.forEach(item2=>{
myArr2.push(item2.sendTime)
})
return myArr.indexOf(item.dataDetail)==index||myArr2.indexOf(item.sendTime)==index
})
失败原因就是分组这里,先判断名字,第一次出现的名字放入数组,之后判断时间,第一次出现的时间也放入另一个数组,但是如果名字1和名字2有相同的时间,也就是出现上面数据示例里id为39,41,47时,47的名字和39重复,47的时间和41重复,导致两个数组都认为他是重复的,但实际上他们并不重复,所以我另外使用了其他方法,参考:
成功代码:
process(arr) {
// 缓存用于记录
const cache = [];
for (const t of arr) {
// 检查缓存中是否已经存在
if (cache.find(c => c.dataDetail === t.dataDetail && c.sendTime === t.sendTime)) {
// 已经存在说明以前记录过,现在这个就是多余的,直接忽略
continue;
}
// 不存在就说明以前没遇到过,把它记录下来
cache.push(t);
}
// 记录结果就是过滤后的结果
return cache;
},
三、数据补位
1.echarts的x轴必须补位少的数据,不然数据起始一样
数据未补位:
数据补位:
而且数据必须按时间来,也就是数据有可能是断的,或者中间缺失,所以前端先将数据分组并获取所有时间(x轴所有数据),并且补位(每个组缺失的时间补齐)
2.获取时间并去重
// echarts的xAxis的data的数据,x轴,只有时间并且时间去重
this.xAxisData = this.duplicateRemoval(res.data.map(item=>{
return item.sendTime
}))
// 数组去重(非对象)
duplicateRemoval(arr){
let newsArr = [];
for (let i = 0; i < arr.length; i++) {
if(newsArr.indexOf(arr[i]) === -1){
// 数组如果不存在该元素则push
newsArr.push(arr[i]);
}
}
return newsArr;
},
3.数据补位
这里我想的有点乱和杂,但是好歹能运行正确,希望有更简单的办法
具体就是先将数据变为[{time:时间,value:数值},...]这样的数据,让时间和数据对应,看看缺少哪些时间节点,将缺少的时间节点和对应的数据补充(时间节点缺失的部分,数值直接赋空就行)
// 数组补位,echarts的seriesdata的数据如果长度不够补位空字符串
// timeList是上面的x轴数据,nameList是按名字分组的数组,data是上面去重后的大数组
complementArray(timeList,nameList,data){
let obj = {}
// 定义对象
for(let i = 0;i<nameList.length;i++){
obj['name'+i] = {
name: nameList[i],
data: []
}
}
// 数据分组
nameList.map((nameItem,index) => {
data.map(item=>{
if(item.dataDetail == nameItem){
obj['name'+index].data.push({dataDetail:item.dataDetail,time: item.sendTime,data: item.dataValue})
}
})
})
// 缺少的数据进行增加,data长度一定是最长的但是有时间缺失和重复,timeList第二长但时间不重复且不缺失,nameList长度一定与obj的第一层对象一样多
// timeList.indexOf(每个对象里的时间)
for(let i = 0;i<nameList.length;i++){
let arr = []
for(let j = 0;j<obj['name'+i].data.length;j++){
arr.push(obj['name'+i].data[j].time)
}
// arr是少的,timeList是总的,看看arr里的数据全不全
timeList.map((item,index)=>{
if(arr.indexOf(item) == -1){
// 如果arr里没有timeList当前元素
obj['name'+i].data.push({dataDetail:obj['name'+i].name,time: item,data: ''})
}
})
}
return obj
},
4.时间排序
将数据处理完毕后要按照时间顺序排列数据,不然列表里对应的时间和图上的不一样,参考:
// obj里的键值对数量取决于之前的按名称的分组
for(let k in obj){
obj[k].data.sort(this.compare('time','positive'))
}
// 排序
compare(prop,align){
return function(a,b){
var value1=a[prop];
var value2=b[prop];
if(align=="positive"){//正序
return new Date(value1)-new Date(value2);
}else if(align=="inverted"){//倒序
return new Date(value2)-new Date(value1);
}
}
}
之后获得对应的值
总代码
// res.data就是后台返回的没有分页的有重复数据的对象数组
// 双条件去重方法1
let arr = this.process(res.data)
// 双条件去重第二种方法
// let arr2 = this.process2(res.data)
// 获取图例长度,也就是大数组分几组,我这里按名称分的
// choseDataNameList是选择的数组,没什么用,数据大概是['name1','name2'……],可以用duplicateRemoval方法获取
this.legendData = this.choseDataNameList.map(item=>{
return item.dataDetail
})
// 获取所有时间节点并去重变为一个大的时间节点数组
this.xAxisData = this.duplicateRemoval(res.data.map(item=>{
return item.sendTime
}))
// echarts的x轴必须补位少的数据,不然数据起始一样
// 需要处理的数据的个数和选择的采集点个数有关
let obj = this.complementArray(this.xAxisData,this.legendData,arr)
// 排序
for(let k in obj){
obj[k].data.sort(this.compare('time','positive'))
}
// debugger
// 处理数据
this.seriesData = this.dataUpData(obj)
// 上面大方法调用的各个小方法
/** *
* 对象数组去重
*
*/
process(arr) {
// 缓存用于记录
const cache = [];
for (const t of arr) {
// 检查缓存中是否已经存在
if (cache.find(c => c.dataDetail === t.dataDetail && c.sendTime === t.sendTime)) {
// 已经存在说明以前记录过,现在这个就是多余的,直接忽略
continue;
}
// 不存在就说明以前没遇到过,把它记录下来
cache.push(t);
}
// 记录结果就是过滤后的结果
return cache;
},
/**
* 数组去重(非对象)
*/
duplicateRemoval(arr){
let newsArr = [];
for (let i = 0; i < arr.length; i++) {
if(newsArr.indexOf(arr[i]) === -1){
// 数组如果不存在该元素则push
newsArr.push(arr[i]);
}
}
return newsArr;
},
// 数组补位,echarts的seriesdata的数据如果长度不够补位空字符串
// timeList是上面的x轴数据,nameList是按名字分组的数组,data是上面去重后的大数组
complementArray(timeList,nameList,data){
let obj = {}
// 定义对象
for(let i = 0;i<nameList.length;i++){
obj['name'+i] = {
name: nameList[i],
data: []
}
}
// 数据分组
nameList.map((nameItem,index) => {
data.map(item=>{
if(item.dataDetail == nameItem){
obj['name'+index].data.push({dataDetail:item.dataDetail,time: item.sendTime,data: item.dataValue})
}
})
})
// 缺少的数据进行增加,data长度一定是最长的但是有时间缺失和重复,timeList第二长但时间不重复且不缺失,nameList长度一定与obj的第一层对象一样多
// timeList.indexOf(每个对象里的时间)
for(let i = 0;i<nameList.length;i++){
let arr = []
for(let j = 0;j<obj['name'+i].data.length;j++){
arr.push(obj['name'+i].data[j].time)
}
// arr是少的,timeList是总的,看看arr里的数据全不全
timeList.map((item,index)=>{
if(arr.indexOf(item) == -1){
// 如果arr里没有timeList当前元素
obj['name'+i].data.push({dataDetail:obj['name'+i].name,time: item,data: ''})
}
})
}
return obj
},
// 按对象数组某一参数排序
compare(prop,align){
return function(a,b){
var value1=a[prop];
var value2=b[prop];
if(align=="positive"){//正序
return new Date(value1)-new Date(value2);
}else if(align=="inverted"){//倒序
return new Date(value2)-new Date(value1);
}
}
},
// 数据处理为series里data想要的
dataUpData(data){
let arr = []
for(let i in data){
let sonArr = data[i].data.map(item=>{
return item.data
})
arr.push({name: data[i].name, type: 'line' ,data: sonArr})
}
return arr
},