0

Problem

Say we have an array of values:

const values = [ 10, 20, 30 ];

Say we have an object that we want to pick up these values:

let props = {
    "hello": null,
    "world": null,
    "other": null
};

I could simply do this:

props.hello = values[0];
props.world = values[1];
props.other = values[2];

That way we'd end up with the desired result:

console.log(props.hello); // Result: 10
console.log(props.world); // Result: 20
console.log(props.other); // Result: 30

Or, more accurately:

console.log(props);
// Result:
// {
//      "hello": 10,
//      "world": 20,
//      "other": 30
// }

The problem is I don't always know what the names of the properties will need to be.

Suppose props is an existing but empty object (or if it does contain properties, they are unrelated to what we're doing here).

props = {};

And suppose we want to compute the name of each property from some related value.

How can I populate props with the names and values I want?

One solution

So I could do this instead, reducing an array of names to an object and then assigning that object's properties back to the original object:

const names = [ "hello", "world", "other" ];
const newProps = names.reduce((p, c, i) => {
    p[c] = values[i];
    return p;
}, {});

props = Object.assign({}, props, newProps);

But this seems messy. For one, it assumes that for every i that exists in values the equivalent would exist for names.

Question

Is there a way to do this with a destructuring assignment?

Yes, there is if I know the names of the properties beforehand:

[ props.hello, props.world, props.other ] = values;

But what if the names exist separately or need to be calculated before they can be assigned to the props object?

let props = {};
const values = [ 10, 20, 30 ];
const names = [ "hello", "world", "other" ];
// [ ...props??? ] = values;
//
// Desired result (props):
// {
//      "hello": 10,
//      "world": 20,
//      "other": 30
// }

One other thing: The reason I'm interested in destructuring, apart from the conciseness of the form, is that I'd like names and values to be considered "immutable" once declared. The object props would ideally be the only changing state in the code. (I've hinted at this by declaring names and values with const, and props with let, although I know in practice these declarations don`t stop the contents of objects and arrays from being changed.)

6
  • 2
    const props = Object.fromEntries(names.map((name, i) => [name, values[i]])) Not using destructuring, but would work. I don't think destructuring alone could do this Commented Feb 23, 2020 at 11:29
  • 2
    You imply that values[i] might not exist. With that precondition, how would you expect any form of array destructuring to work in the first place? Commented Feb 23, 2020 at 11:32
  • @blex Thanks. Yes, your line of code is a version of my reduce function (although more concise). I suspect you're right that it's not possible with destructuring alone but wanted to throw the question out there in case somebody had figured out a way. Commented Feb 23, 2020 at 11:40
  • @str I probably need to articulate this better. I suppose I don't like the assumption that because i necessarily exists in names, it would also exist in values. Destructuring allows for default values where the property doesn't exist but also has a rest operator for properties that do but might not otherwise be captured. It seems like a neater way to handle this... if it's even possible. Commented Feb 23, 2020 at 11:43
  • @str With any luck, the question is a little clearer now. Commented Feb 23, 2020 at 11:50

2 Answers 2

3

You could iterate the names and values at the same time for assignment.

let values = [10, 20, 30],
    props = {},
    names = ["hello", "world", "other"];

for (props[names.shift()] of values) ;

console.log(props);

Another thinkable solution, but with hardcoded object reference.

let values = [10, 20, 30],
    props = {},
    names = ["hello", "world", "other"];

[props[names.shift()], props[names.shift()], props[names.shift()]] = values;

console.log(props);

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

2 Comments

Thanks. Interesting solution and you're right that this "iterates" both structures at the same time, albeit by changing the names array as you go. The question was more about doing this with a destructuring assignment. I was hoping to avoid changes to state like altering the original array -- I'll try to make that clearer in the question.
I've added that point about changing and state to the question now. Thanks for your answer -- it helped me to better refine what I'm trying to achieve.
0

The expected result could be obtained as follows:

let values = [ 10, 20, 30 ];
let names = [ "hello", "world", "other" ];
let props = {};

names.forEach((name, index) => props[name] = values[index]);
console.log(props);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.