自定义sortData排序遇toLowerCase错误,求字符串转换排序方案
问题分析与解决
问题描述
尝试使用自定义的sortData函数对目标JSON数组排序,处理region字段时先通过JSON.parse解析,再拼接字符串存入新数组并JSON.stringify转回,但排序时触发"toLowerCase is not a function"错误,系统仍将输入识别为对象而非字符串。
自定义排序函数
export const sortData = (data, sortColumn, sortDirection) => { if ( isNotNullOrUndefined(data) && isNotNullOrUndefined(sortColumn) && isNotNullOrUndefined(sortDirection) ) { data.sort((firstElement, secondElement) => { // Move null/empty values to last if (!isNotNullOrUndefined(firstElement[sortColumn]) || firstElement[sortColumn] === "") { return 1; } if (!isNotNullOrUndefined(secondElement[sortColumn]) || secondElement[sortColumn] === "") { return -1; } // Handle custom date sorting if (isCustomDate(firstElement[sortColumn]) && isCustomDate(secondElement[sortColumn])) { const milliSecValue1 = getMilliSecFromDateString(firstElement[sortColumn]); const milliSecValue2 = getMilliSecFromDateString(secondElement[sortColumn]); return sortDirection === "ascending" ? milliSecValue1 - milliSecValue2 : milliSecValue2 - milliSecValue1; } // Handle numeric sorting if (isNumeric(firstElement[sortColumn]) && isNumeric(secondElement[sortColumn])) { const numValue1 = parseFloat(firstElement[sortColumn]); const numValue2 = parseFloat(secondElement[sortColumn]); return sortDirection === "ascending" ? numValue1 - numValue2 : numValue2 - numValue1; } // Handle Text sorting if (firstElement[sortColumn].toLowerCase() < secondElement[sortColumn].toLowerCase()) { return sortDirection === "ascending" ? -1 : 1; } if (firstElement[sortColumn].toLowerCase() > secondElement[sortColumn].toLowerCase()) { return sortDirection === "ascending" ? 1 : -1; } return 0; }); } return data; };
目标JSON数组
[ { "NA": { "Date": "2023-06-19", "Time": "13:01:00", "Timezone": "PST" } }, { "EU": { "Date": "2023-06-19", "Time": "13:01:00", "Timezone": "GMT" } }, { "IN": { "Date": "2023-06-19", "Time": "13:01:00", "Timezone": "IST" } } ]
原始处理代码
var regionsData = JSON.parse(element[0]["region"]); var addRegionData = []; regionsData.forEach((value) => { addRegionData.push( Object.keys(value).toString() + " " + value[Object.keys(value)[0]].Date + " " + value[Object.keys(value)[0]].Time + " " + value[Object.keys(value)[0]].Timezone + " " ); dataObj.regions = [JSON.stringify(addRegionData)]; });
错误原因
- 数据结构错误:原始处理代码中
dataObj.regions = [JSON.stringify(addRegionData)]将整个数组字符串化后放入一个新数组,导致sortData处理时,firstElement[sortColumn]指向的是包含整个数组字符串的元素,而非单个region的字符串;甚至如果sortColumn对应的值仍是原始对象,调用toLowerCase自然会报错。 - 类型未确保:
sortData的文本排序部分未确保目标值是字符串类型,若传入的是对象或其他非字符串类型,调用toLowerCase会直接抛出错误。
修复方案
方案1:修正数据处理逻辑
先将原始JSON数组转换为sortData可直接处理的结构,每个元素包含明确的字符串类型字段:
// 假设regionsData是解析后的目标JSON数组 const processedData = regionsData.map(item => { const regionKey = Object.keys(item)[0]; const regionInfo = item[regionKey]; return { region: `${regionKey} ${regionInfo.Date} ${regionInfo.Time} ${regionInfo.Timezone}` }; }); // 此时调用sortData,sortColumn传入"region" const sortedData = sortData(processedData, "region", "ascending");
- 转换后每个元素是包含
region字符串字段的对象,sortData读取firstElement["region"]时直接拿到字符串,可正常调用toLowerCase。
方案2:增强sortData的类型兼容性
在文本排序部分先将值转换为字符串,避免非字符串类型导致的错误:
export const sortData = (data, sortColumn, sortDirection) => { if ( isNotNullOrUndefined(data) && isNotNullOrUndefined(sortColumn) && isNotNullOrUndefined(sortDirection) ) { data.sort((firstElement, secondElement) => { let val1 = firstElement[sortColumn]; let val2 = secondElement[sortColumn]; // Move null/empty values to last if (!isNotNullOrUndefined(val1) || val1 === "") { return 1; } if (!isNotNullOrUndefined(val2) || val2 === "") { return -1; } // 统一转换为字符串,避免类型错误 val1 = String(val1); val2 = String(val2); // Handle custom date sorting if (isCustomDate(val1) && isCustomDate(val2)) { const milliSecValue1 = getMilliSecFromDateString(val1); const milliSecValue2 = getMilliSecFromDateString(val2); return sortDirection === "ascending" ? milliSecValue1 - milliSecValue2 : milliSecValue2 - milliSecValue1; } // Handle numeric sorting if (isNumeric(val1) && isNumeric(val2)) { const numValue1 = parseFloat(val1); const numValue2 = parseFloat(val2); return sortDirection === "ascending" ? numValue1 - numValue2 : numValue2 - numValue1; } // Handle Text sorting const lowerVal1 = val1.toLowerCase(); const lowerVal2 = val2.toLowerCase(); if (lowerVal1 < lowerVal2) { return sortDirection === "ascending" ? -1 : 1; } if (lowerVal1 > lowerVal2) { return sortDirection === "ascending" ? 1 : -1; } return 0; }); } return data; };
- 提前将
val1和val2转换为字符串,确保后续调用toLowerCase时不会因类型错误报错;同时后续的日期、数值判断也基于字符串进行,不影响原有逻辑。
完整示例
结合两种方案,处理并排序数据:
// 解析原始数据 const regionsData = JSON.parse(element[0]["region"]); // 转换为标准结构 const processedData = regionsData.map(item => { const regionKey = Object.keys(item)[0]; const regionInfo = item[regionKey]; return { region: `${regionKey} ${regionInfo.Date} ${regionInfo.Time} ${regionInfo.Timezone}` }; }); // 使用增强后的sortData排序 const sortedData = sortData(processedData, "region", "ascending");
内容的提问来源于stack exchange,提问作者Zubair Amjad
相关产品推荐
相关产品推荐

