-6

I have an object obj; and I then obtain an array arr of key-value pairs. Assuming that the key sets of obj and of arr are disjoint (i.e. no key appears in both) - how do I efficiently add all pairs in arr into obj?

Should I just use a loop and not worry about it? :

arr.forEach(pair => { obj[pair.key] = pair.value; }); 

can I (and should I) use spread syntax somehow? Or - is there another, more efficient way to do it?

Notes:

  • I originally assumed that there is some obvious idiom for this action (as I am not a seasoned JS developer); but - perhaps there just isn't one.
  • If the answer is "it depends", please say what it depends on (e.g. on the JS engine, sizes of the object and of the array, lower execution time vs lower memory use etc.)
8
  • 1
    @einpoklum You should use the first solution in a loop if it works since that is the most intuitive way. Commented Nov 16 at 23:05
  • 1
    @ADyson still answerable. If anybody is in the same situation, they can google for a solution and find it. If the question isn't deleted. We're not a help desk - we don't need to close a question because there is a solution already. Moreover, we can offer other well known solutions and explain the benefits or drawbacks of each. Thus future visitors will be able to choose what fits their situation. Overall, I don't see at all how this isn't a Good Subjective. Although, I don't even think it's subjective. Commented Nov 17 at 9:17
  • 3
    @einpoklum efficient in what way? Runs at a certain speed, uses less lines of code, uses less memory? There are different ways to be "efficient". As I've mentioned a few times...be specific, please. And if you want it faster or smaller or whatever then please set a desired target Commented Nov 17 at 9:44
  • When you say spread, do you mean this? arr.forEach(({ key, value }) => obj[key] = value); Alternative for (const { key, value } of arr) obj[key] = value; Commented Nov 17 at 11:31
  • @mplungjan : Well, my first idea was {...obj, ...arr}, but it seems that doesn't work. Commented Nov 17 at 15:22

1 Answer 1

1

Should I just use a loop and not worry about it?

That's what I'd do.

If you really care that much about performance here, then what you should really do is profile it with a realistic dataset (over all the platforms you plan to support, probably and weighing what you get by how much you care about each one). Web browser devtools usually give you the ability to profile over time and memory consumption.

If the answer is "it depends", please say what it depends on (e.g. on the JS engine, sizes of the object and of the array, lower execution time vs lower memory use etc.)

Uh, ... Yes.

And this (and the number of variables, and the fact that how JS engines implement the spec is up to them, and could change in new releases) is why you should profile (regularly, assuming you target platforms where end-user software auto-updates and you don't get to choose the engine version), if this really matters to you.

I don't think I've personally ever found myself worrying over or caring about that degree of performance with a setup like this. This is JS. Though people have put commendable work into making performant engines, and I commend you about caring about performance (as for many other considerations that benefit the end-user, I wish people cared more about it), the language just wasn't really built for performance. It's not that practical to worry about it for every single thing, and so you should profile and focus your attention to where it will make the most difference, when that difference reaches the threshold of mattering to you.

The degree to which I'd care is in deciding whether obj here would be more fitting as a JS object, or as a Map. In general, if the keys of the map are going to be relatively dynamic over the thing's lifetime, and especially if there will be many keys, go with a Map. JS objects and Maps are typically implemented differently. If you want to read about details of what sorts of optimization a JS engine might do for a JS object, see for example What's up with monomorphism (from which you might take away that if you're going to be doing this operation in question many times, and each time, with the same keys in the same order of visitation, with a target object with the same shape, and you don't expect keys to be removed from those objects in different ways afterwards, it might be a good case to use a JS object; but if it really matters, again, profile).

If this is some routine worth optimizing to you, I'd also be thinking about (if you can) the structure/type of the input. Ex. if the input types are numeric, there could be benefit in refactoring to use typed arrays.

As an aside here, check out if your engine has a blog where they talk about performance things. v8 does, and you can find things like this, this, this.

So basically (and these are explicitly frame challenges),

  1. Profile, and focus your attention and time on what matters.
  2. Choose data types that suit the workload. Get performance from picking appropriate types.

Note that your arr.forEach(pair => { obj[pair.key] = pair.value; }); can also be written as arr.forEach(({key,value}) => obj[key] = value); (and if your array of key-value pairs contained arrays of length 2 instead (like [key, value]), you could do arr.forEach(([k,v]) => obj[k] = v);), but this would mostly just be a matter of syntax preference (if you had to really care about platform support, I'd check platform support tables about whether that destructuring syntax is available on all your platforms).

You could also use Array.prototype.reduce instead of Array.prototype.forEach, and one could make an argument that this semantically makes more sense, but personally, I think that would be a matter of preference. If the performance really mattered, again, profile/benchmark.

For educational purposes, note that if your key-value pairs were arrays of length 2 (like [k, v]), you could also write this as Object.assign(obj, Object.fromEntries(arr)).

Sign up to request clarification or add additional context in comments.

1 Comment

"Typed arrays" - you mean these? Interesting. Currently my keys are (not very long) strings with complex contents, and my values are arrays-of-URIs, i.e. arrays-of-string-references (the URIs also exist independently of my data structure). Finally - thanks for pointing out I may prefer to hold my key-value pairs as length-two-arrays. I actually think I may already be doing that in my actual code, and should have probably done son the question as well. Maybe I still should.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.