Javascript -对数组进行分组,然后根据长度对分组结果进行排序



这是数组;

var dataArr = [
{
"permalink": /* link*/
"subreddit": "mac"
}, {
"permalink": /* link*/
"subreddit": "worldnews"
}, {
"permalink": /* link*/
"subreddit": "MushroomGrowers"
}, {
"permalink": /* link*/
"subreddit": "chrome"
}, {
"permalink": /* link*/
"subreddit": "onions"
}, {
"permalink": /* link*/
"subreddit": "onions"
}, {
"permalink": /* link*/
"subreddit": "SquaredCircle"
}.....
]

基于"subreddit",分组似乎很简单。键使用下划线

const grouped = _.groupBy( dataArr, 'subreddit' )

返回一个类似如下的对象

{
ArtisanVideos: [
{
"permalink": ' link ',
subreddit: "ArtisanVideos"
},
{
"permalink": ' link ',
subreddit: "ArtisanVideos"
},
{
"permalink": ' link ',
subreddit: "ArtisanVideos"
}
],
chrome: [
{
"permalink": ' link ',
subreddit: "chrome"
}
],
laravel: [
{
"permalink": ' link ',
subreddit: "laravel"
},
{
"permalink": ' link ',
subreddit: "laravel"
},
{
"permalink": ' link ',
subreddit: "laravel"
}
],
mac: [
{
"permalink": ' link ',
subreddit: "mac"
}
]
}

现在,如何根据数组

的长度对分组对象进行排序?

从我上面的评论…

"如果OP依赖在对象的键插入顺序(尽管它甚至可以工作)上(因为这是OP要求的),那么OP的整个数据处理方法就有问题了。我们能做的是……从分组条目的前一个对象创建对象项的排序数组。">

下一个提供的解决方案与已经提出的完全相同。

为了达到中间分组的目的,我们可以将给定的数据结构reduce为分组条目的对象(每个条目包含一些先前数据数组项的数组)。

每个entries现在可以被mapped到仍然未排序的结果数组的自己的对象,在最后一步将sort通过每个对象的唯一数组值length-属性或通过单个属性名称(键)的locale比较。

function groupAndCollectBySameKeyValue({ key, result }, item) {
const groupValue = item[key];
(result[groupValue] ??= []).push(item);
return { key, result };
}
var dataArr = [
{ permalink: 'link', subreddit: 'laravel' },
{ permalink: 'link', subreddit: 'mac' },
{ permalink: 'link', subreddit: 'ArtisanVideos' },
{ permalink: 'link', subreddit: 'laravel' },
{ permalink: 'link', subreddit: 'ArtisanVideos' },
{ permalink: 'link', subreddit: 'chrome' },
{ permalink: 'link', subreddit: 'ArtisanVideos' },
{ permalink: 'link', subreddit: 'laravel' },
];
console.log(
dataArr
.reduce(groupAndCollectBySameKeyValue, {
key: 'subreddit',
result: {},
})
.result
);
console.log(
Object
.entries(
dataArr
.reduce(groupAndCollectBySameKeyValue, {
key: 'subreddit',
result: {},
})
.result
)
// create object from grouped entry (key-value pair).
.map(([key, value]) => ({ [key]: value }))
.sort((a, b) =>
// ... either by array length ...
Object.values(b)[0].length - Object.values(a)[0].length
// ... or by locale alphanumeric precedence.
|| Object.keys(a)[0].localeCompare(Object.keys(b)[0])
)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

原因之一也可以达到OP的原始目标,但不建议这样做。我们不应该真正依赖于对象的键插入顺序。

function groupAndCollectBySameKeyValue({ key, result }, item) {
const groupValue = item[key];
(result[groupValue] ??= []).push(item);
return { key, result };
}
var dataArr = [
{ permalink: 'link', subreddit: 'laravel' },
{ permalink: 'link', subreddit: 'mac' },
{ permalink: 'link', subreddit: 'ArtisanVideos' },
{ permalink: 'link', subreddit: 'laravel' },
{ permalink: 'link', subreddit: 'ArtisanVideos' },
{ permalink: 'link', subreddit: 'chrome' },
{ permalink: 'link', subreddit: 'ArtisanVideos' },
{ permalink: 'link', subreddit: 'laravel' },
];
console.log(
dataArr
.reduce(groupAndCollectBySameKeyValue, {
key: 'subreddit',
result: {},
})
.result
);
console.log(
Object
.entries(
dataArr
.reduce(groupAndCollectBySameKeyValue, {
key: 'subreddit',
result: {},
})
.result
)
.sort(([aKey, aValue], [bKey, bValue]) =>
// array length first, or locale property name comparison.
bValue.length - aValue.length || aKey.localeCompare(bKey)
)
.reduce((result, [key, value]) =>
// create object by aggregating entries while following
// the above sorted key precedence / key insertion order.
Object.assign(result, { [key]: value }), {}
)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }

最新更新