对象数组按某个属性的某个顺序连续排序

对象数组按某个属性的某个顺序连续排序

问题描述

按照数据中love这个属性去排序,而且这个顺序必须是“乒乓球、羽毛球、篮球”排序

原始数据如下:

    const data = [

{

name: '李',

love: '篮球'

},

{

name: '李',

love: '乒乓球'

},

{

name: '李',

love: '羽毛球'

},

{

name: '张',

love: '乒乓球'

},

{

name: '张',

love: '羽毛球'

},

{

name: '张',

love: '篮球'

},

{

name: '吴',

love: '羽毛球'

},

{

name: '吴',

love: '乒乓球'

},

]

需要的结果数据如下:

    const data = [

{

name: '李',

love: '乒乓球'

},

{

name: '李',

love: '羽毛球'

},

{

name: '李',

love: '篮球'

},

{

name: '张',

love: '乒乓球'

},

{

name: '张',

love: '羽毛球'

},

{

name: '张',

love: '篮球'

},

{

name: '吴',

love: '乒乓球'

},

{

name: '吴',

love: '羽毛球'

},

]


回答:

从题主给的结果数据来看,并不是单纯的按 love 来排序,而是「先按 name 再按 love 的双重排序」,而且

  • name 不是按字母序,而是按先后出现的顺序
  • love 是按“乒乓球、羽毛球、篮球”的顺序

其中,按 name 出现序需要提前遍历数组,把顺序排出来;或者在排的过程中来产生(因为是顺序,可以在过程中来产生)。

下面这个例子是提前产生的

/**

* 从给定的字符串数组生成序数映射表

* @param { string[] } list

* @returns

*/

function makeSerialsMap(list) {

return Object.fromEntries(list.map((v, i) => [v, i]));

}

/**

* 排序

*/

function sort(data) {

const nameSerials = (() => {

const dict = new Set();

const names = data

.map(({ name }) => {

if (dict.has(name)) { return undefined; }

dict.add(name);

return name;

})

.filter(name => name);

return makeSerialsMap(names);

})();

console.log(nameSerials); // { '李': 0, '张': 1, '吴': 2 }

// 为 3 个 love 依序关联一个数组,并形成查找表

const loveSerials = makeSerialsMap(["乒乓球", "羽毛球", "篮球"]);

console.log(loveSerials); // { '乒乓球': 0, '羽毛球': 1, '篮球': 2 }

return data

.sort((a, b) => {

// 先按姓名排序(这里暂时没按出现的先后顺序

const nameDiff = nameSerials[a.name] - nameSerials[b.name];

if (nameDiff) { return nameDiff; }

// 然后按 love 对应的序数来排序

return loveSerials[a.love] - loveSerials[b.love];

});

}

其中,生成 nameSerials 过程(IIFE 中)中的 names 可以简单地用一句话产生

const names = [...new Set(data.map(({ name }) => name))];

虽然(可能仅在某些环境下)效果还是如预期,但是 Set 本身不应保证排序,所以不同的 JS Runtime 实现有可能不同,所以不这样用。

另一种方法,在过程中产生 nameSerials,其实就是在取序数的时候,检查如果这个 name 不存在于集合中,就把它保存进去,映射到一个“尾值”(一般可以用 Set.prototype.size),并返回。具体代码就不写了,可以自己试试。


回答:

你的题目描述似乎存在问题,
如果按 「按照数据中love这个属性去排序,而且这个顺序必须是“乒乓球、羽毛球、篮球”排序」 实现的话

在线代码演示

但按你后面提供的第二份数据你的目的似乎是 「先将数据按 name 排序,然后再按数据中love这个属性去排序,而且这个顺序必须是“乒乓球、羽毛球、篮球”排序」
实现方案如下

在线代码演示

不过这里的排序是 李 吴 张 ,不清楚你第二份数据中的张排第二位是按照什么规则来的,需要你按照自己的规则稍微修改一下


回答:

const data = [

{

name: '李',

love: '篮球'

},

{

name: '李',

love: '乒乓球'

},

{

name: '李',

love: '羽毛球'

},

{

name: '张',

love: '乒乓球'

},

{

name: '张',

love: '羽毛球'

},

{

name: '张',

love: '篮球'

},

{

name: '吴',

love: '羽毛球'

},

{

name: '吴',

love: '乒乓球'

},

]

const map = data.reduce((map, item) => {

const { love } = item;

if (!map.get(love)) {

map.set(love, []);

}

map.get(love).push(item);

return map;

}, new Map());

const sortLove = ['乒乓球', '羽毛球', '篮球'];

const length = Math.max(...[...map.values()].map(item => item.length));

const result = [];

for(let i = 0; i < length; i++) {

sortLove.forEach(key => {

const item = map.get(key)?.[i];

if (item) {

result.push(item);

}

})

}

console.log(result);


回答:

const data = [

{

name: "李",

love: "篮球"

},

{

name: "李",

love: "乒乓球"

},

{

name: "李",

love: "羽毛球"

},

{

name: "张",

love: "乒乓球"

},

{

name: "张",

love: "羽毛球"

},

{

name: "张",

love: "篮球"

},

{

name: "吴",

love: "羽毛球"

},

{

name: "吴",

love: "乒乓球"

}

];

let res = [];

const sorts = ["乒乓球", "羽毛球", "篮球"];

while (data.length) {

sorts.forEach(item => {

const idx = data.findIndex(r => r.love == item);

idx > -1 && res.push(data.splice(idx, 1));

});

}

console.log(res);

以上是 对象数组按某个属性的某个顺序连续排序 的全部内容, 来源链接: utcz.com/p/935635.html

回到顶部