change multiple key names using reduce and preserve position

have the following code. Is it possible to run reduce only once to change the key names? In the example below, I run the reduce function twice. How this can become more efficient? Can this be done with one iteration?

    const newArrayOfObj = rows.map(row => {
        row = Object.keys(row).reduce(
            (a, key) =>
             ({
                ...a,
                [key === 'redirects' ? 'clicks' : key]: row[key],
            }),
            {},
        );

        row = Object.keys(row).reduce(
            (a, key) =>
             ({
                ...a,
                [key === 'tags' ? 'external impressions' : key]: row[key],
            }),
            {}
        );
2 Likes

Just put them in the same function, can just use if/else, or call a function to do it or whatever. You don’t have to try to squash everything onto one line

Also, minor, but although using object spread with the implicit return looks nice and compact, it’s bad from a perf point of view because, for no reason other than terseness, you are creating an entirely new object and running an inner loop that increases in size every iteration of reduce. This doesn’t matter a great deal when learning, with small arrays, but it’s defo a bad habit to get into.

a[key] = row[key]; return a is fine and works great.

2 Likes

thanks for the reply but I am not sure how this can be done. can you show me how would you do it?

1 Like

Do you understand what the code you’ve posted does exactly? What I mean is, did you write that code, and do you understand the syntax, or is it pasted from somewhere?

1 Like

I understand the code but not sure how to modify as you suggest.

1 Like

Well, for starters you’re mapping over the array of objects, so every loop of that you have a function that returns an object. You need to write complicated nested function calls inside that, just change the keys, for example,

if ("somekey" in row) {
  row.newkey = row.something;
}
delete row.something;
return row;

This is why I ask if you’ve just copy pasted something: you’re doing something unnecessarily complicated, and doing it twice instead of just once

1 Like

this will cause me to lose the position of the key.

1 Like

Why does that matter? The advice there is not particularly good either, you already have the row, ie the object. So if it’s really important the order is preserved just (for example), use a for…in loop

oldObj = { given_name: "Dan", family_name: "Couper" }
newObj = {};

for (k in oldObj) {
  switch (k) {
    case "given_name":
      newObj.givenName = oldObj.given_name;
      break;
    case "family_name":
      newObj.familyName = oldObj.family_name;
      break;
    default:
      newObj[k] = oldObj[k];
  }
}

Or loop over Object.keys(oldObj), or you can use Object.defineProperties. There are loads of ways to do this that do not involve running reduce over the object once for every single property you want to change the name of

1 Like

it matters for my requirement

1 Like

You can still use reduce as well, there’s just no reason why you wouldn’t put the logic into one function instead of calling reduce in every single property you want to change.

This is, again, why I asked if you understood the code: the callback to reduce is just a function, you don’t have to make it as terse as possible, you can just write logic in there

1 Like

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.