Jee Mok
Jee Mok

Reputation: 6556

Alternative way to map object key values

What is the alternative/best way to map through an object key-values without using forEach?

This is what I have currently:

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 is an object like:

{
  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 }
  ]
}

The final output is like:

{
  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 }
  ]
}

is there a better/cleaner way to do this?

Upvotes: 1

Views: 2984

Answers (2)

Pengcheng
Pengcheng

Reputation: 323

You can also use map for looping the object entries and splice for cutting off the array length:

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;
};

Upvotes: 0

T.J. Crowder
T.J. Crowder

Reputation: 1074335

I'd look at Object.entries (new as of ES2017 but polyfillable) and destructuring in a for-of loop.

If nothing else has access to the arrays on source (which I tend to assume, since sort works in-place, so the code already modifies the original array; but at the same time, source is coming in from outside, so...):

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;
}

If something else has access to those arrays and you shouldn't modify them other than sorting them, then you'll need your original length check and 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;
}

Your code suggests you may not have realized sort works in-place since you were assigning the result back to the original location. If so and you didn't intend to sort the arrays in-place, you'll need to copy the arrays before sorting:

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;
}

You could replace

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

with

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

if you like, but that'll use an iterator, which is more overhead than slice.

Upvotes: 3

Related Questions