【问题标题】:Sort an object by an optional field without losing the keys按可选字段对对象进行排序而不会丢失键
【发布时间】:2019-12-30 17:59:39
【问题描述】:

我有以下对象,我想按其优先级字段排序。

{
    anchor_block: {
        label: 'Anker-Block',
        priority: 100,
        description: ...,
        fields: ...
    },
    categories_block: {
        label: 'Categories-Block',
        description: ...,
        fields: ...
    },
    contact_block: {
        label: 'Kontakt-Block',
        description: ...,
        fields: ...
    },
    employee_block: {
        label: 'Mitarbeiter-Block',
        priority: 90,
        description: ...,
        fields: ...
    }
}

我尝试用 lodash 对它们进行排序:

_.orderBy(blocks, ['priority'], ['desc']);

但是这个解决方案会从我的对象中删除所有键(因为它返回一个数组),并且它还将没有优先级字段的键放在顶部:

[
    {
        label: 'Categories-Block',
        description: ...,
        fields: ...
    },
    {
        label: 'Kontakt-Block',
        description: ...,
        fields: ...
    },
    {
        label: 'Anker-Block',
        priority: 100,
        description: ...,
        fields: ...
    },
    {
        label: 'Mitarbeiter-Block',
        priority: 90,
        description: ...,
        fields: ...
    },
]

你们中有人知道如何用 lodash 解决这个问题吗?我想避免自己重复它,因为我确信这是可能的,我只是不明白它。

【问题讨论】:

  • 对象在 JavaScript 中没有排序。
  • @Barmar 你确定吗?我们曾经说过,在迭代对象时无法保证键的顺序,但这似乎不再正确。如果键是按特定顺序插入的,那么我们不能说对象可以排序吗?
  • 自 es2020 以来,属性顺序在所有情况下都是明确定义的。如果没有整数索引属性且不涉及符号,则该顺序为can be freely manipulated,但这绝不意味着应该这样做。使用适合任务的适当数据结构,而不是对象的属性顺序。
  • 非常感谢。你会选择什么样的数据结构?我应该将它们添加到数组中,还是如何保留顺序?

标签: javascript sorting object lodash


【解决方案1】:

更新答案:方法是存储所有键,根据您想要的顺序对它们进行排序,然后使用这些键以所需的顺序从原始对象中检索值。

let obj = {
    anchor_block: {
        label: 'Anker-Block',
        priority: 100,
        description: '...',
        fields: '...'
    },
    categories_block: {
        label: 'Categories-Block',
        description: '...',
        fields: '...'
    },
    contact_block: {
        label: 'Kontakt-Block',
        description: '...',
        fields: '...'
    },
    employee_block: {
        label: 'Mitarbeiter-Block',
        priority: 90,
        description: '...',
        fields: '...'
    }
}
/*
    Plain JS, no Lodash
*/

let sortedKeys = Object.keys(obj);
sortedKeys.sort((key1, key2) => {
    let p1 = obj[key1].priority || 0, p2 = obj[key2].priority || 0;
    if(p1<p2)
        return 1; // Put key2 first in sorted order
    return -1; // Else, put key1 first in sorted order
    /*
        For ascending order, do this
        if(p1<p2)
            return -1;
        return 1;
    */
})

sortedKeys.forEach(key => {
    console.log(key,"-->",obj[key]);
})

输出

anchor_block --> { label: 'Anker-Block',
  priority: 100,
  description: '...',
  fields: '...' }
employee_block --> { label: 'Mitarbeiter-Block',
  priority: 90,
  description: '...',
  fields: '...' }
categories_block --> { label: 'Categories-Block', description: '...', fields: '...' }
contact_block --> { label: 'Kontakt-Block', description: '...', fields: '...' }

【讨论】:

  • 感谢您的努力,但这并不像我预期的那样有效。不就是转移邻居吗?我认为这需要与对象中的项目一样多次运行才能获得所需的结果。
  • Doesn't it just shift the neighbors?,请详细说明这一点。如果结果不是您的预期输出,请提供示例输出。
  • 这就是我的想法,我第一次测试这个剪断。我现在创建了一个 jsfiddle (jsfiddle.net/40xh89vb/1),我无法订购这些物品。
  • 你说得对,我的排序比较器函数出现错误。我已经在更新的答案中修复了它。
  • 很高兴能帮上忙!
猜你喜欢
  • 2015-11-27
  • 1970-01-01
  • 1970-01-01
  • 2011-05-16
  • 2015-03-11
  • 1970-01-01
相关资源
最近更新 更多