映射对象键值的另一种方法

时间:2018-10-11 08:24:23

标签: javascript

不使用forEach来映射对象键值的替代/最佳方法是什么?

这是我目前拥有的:

sortObject(source) {
    const object = Object.assign({}, source);

    Object.keys(object).forEach(key => {
      // Sort array by priority (the higher the number, the higher the priority)
      object[key] = object[key].sort((a, b) => b.priority - a.priority);

      // Limit the array length to the 5
      if (object[key].length > 5) {
        object[key] = object[key].slice(0, 5);
      }
    });

    return object;
}

source是一个像这样的对象:

{
  base: [
    { id: 1, priority: 5 },
    { id: 2, priority: 10 },
    { id: 3, priority: 1 },
    { id: 4, priority: 5 },
    { id: 5, priority: 15 }
  ],
  extra: [
    { id: 1, priority: 1 },
    { id: 2, priority: 5 },
    { id: 3, priority: 10 }
  ],
  additional: [
    { id: 1, priority: 5 },
    { id: 2, priority: 10 },
    { id: 3, priority: 10 },
    { id: 4, priority: 15 },
    { id: 5, priority: 1 },
    { id: 6, priority: 29 },
    { id: 7, priority: 100 },
    { id: 8, priority: 100 },
    { id: 9, priority: 5 }
  ]
}

最终输出如下:

{
  base: [
    { id: 5, priority: 15 },
    { id: 2, priority: 10 },
    { id: 1, priority: 5 },
    { id: 4, priority: 5 },
    { id: 3, priority: 1 }
  ],
  extra: [
    { id: 3, priority: 10 },
    { id: 2, priority: 5 },
    { id: 1, priority: 1 }
  ],
  additional: [
    { id: 7, priority: 100 },
    { id: 8, priority: 100 },
    { id: 6, priority: 29 },
    { id: 4, priority: 15 },
    { id: 2, priority: 10 }
  ]
}

是否有更好/更清洁的方法?

2 个答案:

答案 0 :(得分:2)

我将研究Object.entries(ES2017以来的新功能,但可填充)并在for-of循环中进行分解。

如果没有其他任何东西可以访问source上的数组(我倾向于假设,因为sort在原位运行 ,所以代码已经修改了原始数组;但同时source是从外面进来的,所以...):

sortObject(source) {
    const object = Object.assign({}, source);

    for (const [key, array] of Object.entries(object)) {
        array.sort((a, b) => b.priority - a.priority);
        array.length = Math.min(array.length, 5);
    }

    return object;
}

如果其他东西可以访问这些数组,除了对它们进行排序之外,您不应该对其进行修改,那么您将需要原始的length检查和slice

sortObject(source) {
    const object = Object.assign({}, source);

    for (const [key, array] of Object.entries(object)) {
        array.sort((a, b) => b.priority - a.priority);
        if (array.length > 5) {
            object[key] = array.slice(0, 5);
        }
    }

    return object;
}

您的代码表明您可能尚未意识到sort可以就地工作,因为您已将结果分配回原始位置。如果是这样,并且您不打算就地对数组进行排序,则需要在排序之前复制数组:

sortObject(source) {
    const object = Object.assign({}, source);

    for (const [key, array] of Object.entries(object)) {
        object[key] = array = array.slice();
        array.sort((a, b) => b.priority - a.priority);
        array.length = Math.min(array.length, 5);
    }

    return object;
}

您可以替换

        object[key] = array = array.slice();
        array.sort((a, b) => b.priority - a.priority);

使用

        object[key] = array = Array.from(array).sort((a, b) => b.priority - a.priority);

如果愿意的话,但是它将使用迭代器,它比slice的开销更大。

答案 1 :(得分:0)

您还可以使用map来循环对象条目,并使用拼接来缩短数组长度:

const getSortedObj = (source) => {
    let obj = Object.assign({}, source);
    Object.entries(obj).map( entry => {
        let [key, arr] = entry;
        arr.sort((a, b) => b.priority - a.priority).splice(Math.min(arr.length, 5));
        return entry;
    });
    return obj;
};
相关问题