数组多重排序问题?

roomsList = [
        { id: 57, room_code: '6-2-101' },
        { id: 75, room_code: '6-2-102' },
        { id: 51, room_code: '6-2-1301' },
        { id: 50, room_code: '6-2-1501' },
        { id: 49, room_code: '6-2-1701' },
        { id: 79, room_code: '6-2-17A02' },
        { id: 56, room_code: '6-2-201' },
        { id: 76, room_code: '6-2-202' },
        { id: 55, room_code: '6-2-301' },
        { id: 77, room_code: '6-2-302' },
        { id: 78, room_code: '6-2-3A02' },
        { id: 54, room_code: '6-2-501' },
        { id: 53, room_code: '6-2-701' },
        { id: 80, room_code: '8-1-101' },
        { id: 84, room_code: '8-1-102' },
        { id: 83, room_code: '8-1-17A01' },
        { id: 87, room_code: '8-1-17A02' },
        { id: 81, room_code: '8-1-201' },
        { id: 85, room_code: '8-1-202' },
        { id: 82, room_code: '8-1-301' },
        { id: 86, room_code: '8-1-3A02' },
        { id: 88, room_code: '9-1-101' },
        { id: 91, room_code: '9-1-102' },
        { id: 90, room_code: '9-1-17A01' },
        { id: 95, room_code: '9-1-17A02' },
        { id: 89, room_code: '9-1-201' },
        { id: 92, room_code: '9-1-202' },
        { id: 93, room_code: '9-1-302' },
        { id: 94, room_code: '9-1-3A02' },
        { id: 96, room_code: '11-1-201' },
        { id: 97, room_code: '11-1-202' },
        { id: 101, room_code: '11-2-17A01' },
        { id: 104, room_code: '11-2-17A02' },
        { id: 98, room_code: '11-2-201' },
        { id: 102, room_code: '11-2-202' },
        { id: 99, room_code: '11-2-301' },
        { id: 103, room_code: '11-2-302' },
        { id: 100, room_code: '11-2-3A01' },
        { id: 66, room_code: '14-1-1002' },
        { id: 65, room_code: '14-1-1102' },
        { id: 64, room_code: '14-1-1202' },
        { id: 63, room_code: '14-1-1302' },
        { id: 62, room_code: '14-1-1402' },
        { id: 61, room_code: '14-1-1502' },
        { id: 60, room_code: '14-1-1602' },
        { id: 59, room_code: '14-1-1702' },
        { id: 58, room_code: '14-1-1802' },
        { id: 74, room_code: '14-1-202' },
        { id: 73, room_code: '14-1-302' },
        { id: 72, room_code: '14-1-402' },
        { id: 71, room_code: '14-1-502' },
        { id: 70, room_code: '14-1-602' },
        { id: 69, room_code: '14-1-702' },
        { id: 68, room_code: '14-1-802' },
        { id: 67, room_code: '14-1-902' }
      ]

解释:
A-B-CDE 代表A栋B单元CD楼的E户
6-2-101 代表6栋2单元1楼的01户
6-2-1501 代表6栋2单元15楼的01户
6-2-17A01 代表6栋2单元17A楼(18楼)的01户
源数据格式为room_list,要求按照以下4个综合排序
1.楼栋号升序; 2.单元号升序; 3.楼层号升序; 4.户号升序;

阅读 2.6k
4 个回答

把3A、17A这种转换成对应的数字(4、18),再比较数字不就完了

roomsList.sort((
  { room_code: codeA },
  { room_code: codeB }
) => {
  let [buildingA, unitA, floorA] = codeA.split('-');
  let [buildingB, unitB, floorB] = codeB.split('-');
  floorA = floorA.replace(/(\d)\D/, ($0, $1) => ++$1);
  floorB = floorB.replace(/(\d)\D/, ($0, $1) => ++$1);
  return buildingA - buildingB || unitA - unitB || floorA - floorB;
});

这种直接用字符串排序即可,因为编码是规律的

  roomsList.sort((a,b)=>{
      let aA= a["room_code"].split('-');
      let bA= b["room_code"].split('-');
      if (aA[0] != bA[0]){
          return  ( parseInt(aA[0]) - parseInt(bA[0]) );
      }
      if (aA[1] != bA[1]){
          return ( parseInt(aA[1]) - parseInt(bA[1]) );
      }
      let a1 = aA[2].substring(0 , aA[2].length -2); // 获取楼层信息
      let a2 = aA[2].substring(aA[2].length -2);     // 获取户号信息
      let b1 = bA[2].substring(0 ,bA[2].length  -2); // 获取楼层信息
      let b2 = bA[2].substring(bA[2].length -2) ;    // 获取户号信息
      if ( a1 != b1){
          if ( parseInt(a1) != parseInt(b1)){
              return ( parseInt(a1) - parseInt(b1) );
          }else{
              return (a1.length - b1.length); // 处理 3 和3A 、 17 和 17A 比较的特殊情况。如果楼号、单元号中也有类似情况,也需要类似处理
          }
      }
      return  ( parseInt(a2, 10) - parseInt(b2,10 ) );
  });

两种方法进行比较,一种是把各分部拆出来,转成数值来进行比较;另一种是把各部分补成“标准”表示(不足 2 位补 0),然后用整个字符串进行比较。

下面的代码两种方法都有

// 这个函数主要是为了两种方法重用,如果确定了一种方法,可以合并到外层处理函数中
function getParts(roomNum) {
    const [building, unit, num] = roomNum.split("-");
    const floor = num.slice(0, -2);
    const room = num.slice(-2);
    return [building, unit, floor, room];
}

// 把每个部分都转换成数字 (Number),特殊的楼层查表处理
//(也可以写转换函数,比如有 A 就将前面部分 + 1)
const getPartsNumbers = (() => {
    const map = {
        "3A": 4,
        "17A": 18
    };

    return (roomNum) => {
        const parts = getParts(roomNum);
        parts[2] = map[parts[2]] ?? parts[2];
        return parts.map(n => parseInt(n));
    };
})();

function getPartsLine(roomNum) {
    let parts = getParts(roomNum);
    const t = parts[2];
    parts = parts.map(s => s.padStart(2, "0"));
    parts[2] = t.padStart(t.endsWith("A") ? 3 : 2, "0");
    return parts.join("-");
}

// 第一种方法,分段比较。就是把房号拆分出来一段一段的比较,直到决出先后顺序
function sortRooms1(list) {
    list.sort((a, b) => {
        const aParts = getPartsNumbers(a.room_code);
        const bParts = getPartsNumbers(b.room_code);
        for (let i = 0; i < 4; i++) {
            const v = aParts[i] - bParts[i];
            if (v !== 0) return v;
        }
        return 0;
    });
    return list;
}

// 第二种方法,直接把房号转成标准格式(假设每段最多 2 位数字),按字符串比较
function sortRooms2(list) {
    list.sort((a, b) => {
        const aNum = getPartsLine(a.room_code);
        const bNum = getPartsLine(b.room_code);
        if (aNum > bNum) { return 1; }
        if (aNum < bNum) { return -1; }
        return 0;
    });
    return list;
}


console.log(sortRooms1(roomsList));
console.log(sortRooms2(roomsList));

示例代码,用起来并不会很优化。比如每次都比较都需要去转换楼层号(转成数值数组或标准字符串),其实干了很多重复工作。可以提前转换好,作为一个属性(比如 sortMark)插到每个对象里去,排序完了再把这个属性删除(如果不影响后续业务留着也可)。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题