js 根据物件里面的数组 如何正确排序?

火爆浪子
  • 2.8k

以下是物件

p1: {
    "data": [
        {
            "time": 5
        },
        {
            "time": 4
        }, ...
    ],
},
p2: {
    "data": [
        {
            "time": 3
        },
        {
            "time": 2
        }, ...
    ],
},
p3: {
    "data": [
        {
            "time": 19
        },
        {
            "time": 17
        }, ...
    ],
}

假设是这样子

我想让其排序是
p3, p1, p2
想根据物件里面自己的数组最新的time数字去排列外层的顺序
类似有最新消息的排最上面一样的意思

const sortable = Object.fromEntries(
 Object.entries(row).sort(([, a], [, b]) => {
  if (a.data[0] && b.data[0]) {
    return a.data[0].time - b.data[0].time;
  }
 })
);

有毛病,可能我思路搞错了
有经验的老哥能否指点迷津?

回复
阅读 754
2 个回答
边城
  • 54.8k
✓ 已被采纳

你自己的答案没太大的毛病

  1. 要从大到小,应该是 b - a 而不是 a - b
  2. 排序一定需要两个值的比较,所以在分支未命中的情况返回 undefined 不合适

对第 2 点,要有策略,如果某个元素的 data 中不存在元素,这个是放在最前,还是最后。这里根据题意,大概应该过滤掉,就算不过滤,也应该放在最后,所以代码改为

const sorted = Object.fromEntries(
    Object.entries(row).sort(([, a], [, b]) =>
        (b.data[0]?.time ?? 0) - (a.data[0]?.time ?? 0))
);

不使用 ?.?? 的代码

下面这个你自己写的没毛病,所以不知道你具体遇到了啥问题。

(b.data[0] && b.data[0].time ? b.data[0].time : 0) -
(a.data[0] && a.data[0].time ? a.data[0].time : 0)

不过用 || 可能稍微简单一点

const sorted = Object.fromEntries(
    Object.entries(row).sort(([, a], [, b]) =>
        ((b.data[0] && b.data[0].time) || 0) - ((a.data[0] && a.data[0].time) || 0)
    )
);

对你那个「更骚」的版本
const sorted = {};
Object.entries(row)
    .map(([key, value]) => {
        let obj = {
            room: key,
            latestTime: (value.data || []).reduce((max, { time }) => Math.max(max, time), 0)
        };
        // 何必这么复杂,如果 data 是空的,直接给个 [] 作为默认值来处理就好了
        // let lastObj = null;
        // if (value.data && value.data.length > 0) {
        //     lastObj = value.data.reduce((a, b) =>
        //         a.time > b.time ? a : b
        //     );
        // }
        // value.latestTime = lastObj ? lastObj.time : 0;
        // Object.assign(obj, value);
        return obj;
    })
    .sort((a, b) => (b.latestTime - a.latestTime))
    .forEach((res) => {
        // console.log(res); // 注1

        // 测试环境没有 this.obj,改成 sorted 了
        Object.assign(sorted, {
            [res.room]: {
                data: res.latestTime,
                // data: res.data,
            },
        });
    });

console.dir(sorted, { depth: null });
let arr = [ {
    "data": [
        {
            "time": 5
        },
        {
            "time": 4
        },
    ],
},
{
    "data": [
        {
            "time": 3
        },
        {
            "time": 2
        },
    ],
},
{
    "data": [
        {
            "time": 19
        },
        {
            "time": 17
        },
    ],
}]

let max = (result,init) => {
    if(init < result){
        return result;
    }
    return init;
}

arr.sort( (i1, i2)=> i2.data.reduce(max).time - i1.data.reduce(max).time )

image.png

宣传栏