如何按属性值拆分数组且保持键的原始顺序?
保持分组后对象键的原始顺序
问题里的核心矛盾在于:普通JavaScript对象在早期JS引擎中不保证键的存储顺序,即便ES6+规范明确了字符串键会保留插入顺序,但如果要严格确保分组后的键顺序和原数组中header_region首次出现的顺序完全一致,更可靠的方式是用Map来做分组存储——因为Map本身就是完全按照键的插入顺序来保存数据的。
修改后的实现方案
你可以调整groupBy函数,先用Map累积分组结果,再按需转换成保留顺序的对象:
function groupBy(arr, property) { // 用Map存储分组,严格保留键的插入顺序 const groupMap = arr.reduce((memo, item) => { const key = item[property]; if (!memo.has(key)) { memo.set(key, []); } memo.get(key).push(item); return memo; }, new Map()); // 将Map转为普通对象(ES2019+支持),对象键顺序与Map一致 return Object.fromEntries(groupMap); } // 你的测试数组 var test_array = [ { "test_name":"vna", "header_region":"vna_results", "header_name":"larm", "value_title":"area"}, { "test_name":"vna", "header_region":"vna_results", "header_name":"larm", "value_title":"area"}, { "test_name":"lma", "header_region":"lma_results", "header_name":"larm", "value_title":"area"}, { "test_name":"lma", "header_region":"lma_results", "header_name":"larm", "value_title":"area"}, { "test_name":"uni", "header_region":"uni_results", "header_name":"larm", "value_title":"area"}, { "test_name":"uni", "header_region":"uni_results", "header_name":"larm", "value_title":"area"} ]; var splitted = groupBy(test_array, 'header_region'); console.log(splitted);
方案为什么有效
Map会严格按照键首次被添加的顺序存储,完美匹配原数组中header_region出现的先后顺序;Object.fromEntries(groupMap)可以将Map转化为普通对象,在支持ES2019及以上的环境中,这个对象的键顺序会和Map的键顺序完全一致。
兼容旧环境的备选方案
如果你的运行环境不支持Object.fromEntries,可以手动遍历Map来构建对象:
function groupBy(arr, property) { const groupMap = arr.reduce((memo, item) => { const key = item[property]; if (!memo.has(key)) { memo.set(key, []); } memo.get(key).push(item); return memo; }, new Map()); const result = {}; // 按Map的插入顺序遍历键值对,构建对象 for (const [key, value] of groupMap) { result[key] = value; } return result; }
这样处理后,splitted对象的键顺序会严格保持vna_results → lma_results → uni_results,和原数组中header_region首次出现的顺序完全一致。
内容的提问来源于stack exchange,提问作者Neha
相关产品推荐
相关产品推荐

