一. 初始数据
const initData = [
{
date: '2024-08',
base: '深圳',
value: 56,
},
{
date: '2024-07',
base: '深圳',
value: 69,
},
{
date: '2024-07',
base: '合肥',
value: 75,
},
{
date: '2024-08',
base: '浙江',
value: 72,
},
];
下面根据上述初始数据,列举常见的需求
二. 根据最新月份的数据进行排序。
完整代码
// 处理日期
const normarizeDate = (date) => {
let formatStr = date;
if (date.includes('-')) {
formatStr = date.replace(/-/g, '');
}
return Number(formatStr);
};
// 对日期进行排序
const getDateList = () => {
const mapDateList = [...new Set(initData.map((item) => item.date))];
const tempList = mapDateList.sort((a, b) => {
const aItem = normarizeDate(a);
const bItem = normarizeDate(b);
return bItem - aItem;
});
return tempList;
};
const getXdata = (data) => {
const maxDate = getDateList()[0];
const xBaseList = [...new Set(data.map((item) => item.base))];
const resultData = xBaseList
.map((item) => {
const selectItem = data.find((subitem) => subitem.base === item && subitem.date === maxDate);
const { value, base } = selectItem ?? {};
return {
value: value ?? 0,
base: base ?? item,
};
})
.sort((a, b) => b.value - a.value);
return resultData.map((item) => item.base);
};
三. 对基地值进行排序,没有的返回null
期望得到
const yData = [
{
name: '2024-08',
data: [72, 56, null],
},
{
name: '2024-07',
data: [null, 69, 75],
},
];
有两种代码方案:
- find + forEach
const getYdata = () => {
const xDataList = getXdata(initData);
const nameList = getDateList();
const nameListMap = nameList.map((item) => {
const valueArray = [];
xDataList.forEach((subitem, subindex) => {
const selectItem = initData.find((yitem) => yitem.base === subitem && item === yitem.date);
valueArray.push(selectItem?.value ?? null);
});
return {
name: item,
data: valueArray,
};
});
return nameListMap;
};
- reduce
const getYdata2 = () => {
const xDataList = getXdata(initData);
const intermediateData = initData.reduce((acc, { date, base, value }) => {
const index = xDataList.indexOf(base);
if (!acc[date]) {
acc[date] = new Array(xDataList.length).fill(null);
}
acc[date][index] = value;
return acc;
}, {});
const resultData = Object.keys(intermediateData)
.sort((a, b) => {
const aItem = normarizeDate(a);
const bItem = normarizeDate(b);
return bItem - aItem;
})
.map((date) => {
return {
data: intermediateData[date],
};
});
return resultData;
};
四. 关于sort使用的几点说明
- 对日期比较也可以直接用newDate
const list = ['2023-07', '2023-09'];
const compareData = () => {
return list.sort((a, b) => {
const aa = new Date(a);
const bb = new Date(b);
return bb - aa;
});
};
const flag = compareData();
console.log(flag);
- 为什么不能直接 bb > aa?
首选来梳理下sort排序的规则
在 JavaScript 的 Array.prototype.sort() 方法中,比较函数 (a, b) 的目的是确定数组元素 a 和 b 的相对顺序。这个比较函数应该返回一个数字,用于指示 a 和 b 的排序关系:
1. 如果返回值小于 0,则 a 会被排在 b 之前(升序)。
2. 如果返回值大于 0,则 b 会被排在 a 之前(降序)。
3. 如果返回值等于 0,则 a 和 b 的相对位置保持不变(尽管实际行为可能依赖于排序算法的稳定性和实现)。
当你写 b - a 时,你实际上是在计算两个数的差。如果 b 大于 a,则差值为正,表示 b 应该排在 a 之前(降序)。如果 a 大于 b,则差值为负,表示 a 应该排在 b 之前(升序的相反情况,但在降序排序中是正确的)。如果 a 等于 b,则差值为 0,表示它们的顺序可以保持不变。
然而,当你写 b > a 时,你得到的是一个布尔值(true 或 false)。在 JavaScript 中,布尔值可以被隐式转换为数字(true 转换为 1,false 转换为 0),但这并不是 sort() 方法期望的比较结果。sort() 方法期望的是一个具体的数字,用于精确控制排序顺序。
如果你只写 b > a 并将其作为比较函数返回,那么实际上会发生以下情况:
如果 b > a,则 true(隐式转换为 1)被返回,但 sort() 方法不会正确地将 b 放在 a 之前进行降序排序,因为 1 只是一个正数,它不代表 b 和 a 之间的具体差值。
如果 b <= a,则 false(隐式转换为 0)被返回,这会导致 sort() 方法认为 a 和 b 相等(在排序的上下文中),但实际上它们可能不相等(只是 b 不大于 a 而已)。
bb -aa 为降序, aa -bb为升序。