1

I have a function that accepts the following arguments:

set(section, field, pair, component, element, value)

The section, field, pair and component are just keys within the Object. They are way-points so we can travel down the hierarchy. Obviously section is the head, our entry point.

element is the target key and the value is the value that will be set.

Since, there are elements at different depths, I would like to do the following:

set('utility', null, null, null, 'exportId', 'banana')

This is for a shallow access, and internally it will do this:

dataObj[section][element] = value;

**/ As in
 * data: {
      utility: {
         exportId: 'banana'
      }
 *  }
 */


In other cases, when the element is deeper inside the Object, it may be required to do the following:

dataObj[section][field][pair][component][element] = value;

What would be the best way, to define the path to the element dynamically, so we skip the keys that are passed in as a 'null'?

for example:

set('history', 'current', null, null, 'fruit', 'apple')

**/ As in
 * data: {
      history: {
         current: {
           fruit: 'apple'
        }
      }
 *  }
 */

will internally be constructed as:

dataObj[section][field][element] = value;

as you might have noticed, we skipped [pair][component] because those slots were passed in as null(s).

1
  • You would be better off with an array and not defined arguments. Simple loop over the array Commented Apr 30, 2019 at 17:33

2 Answers 2

1

Instead of having a long list of specific parameters, just pass an object to the function. this way you only pass what you need to and there won't be any "null" references to deal with on the call.

Using this implementation, this call can be shortened to something like this:

Your current implementation:

 set('utility', 'current', null, null, 'exportId', 'banana')

Using an object as the parameter:

set({
   section:'utility', 
   field:'current', 
   element: 'exportId', 
   value:'banana'
});
Sign up to request clarification or add additional context in comments.

1 Comment

Let me test it. I think I had it setup like that before. Not exactly the answer to my question, as it will require changing the implementation, but it might work as a solution. I would be happy to accept it and move on, as it might render my whole question a bit pointless.
0

You could use rest parameters to get the arguments passed to an array. Then create an object using reduceRight

function set(...paths) { 
  return paths.reduceRight((r, key, i) => key !== null ? { [key] : r } : r)  
}

console.log(set('history', 'current', null, null, 'fruit', 'apple'))
console.log(set('utility', null, null, null, 'exportId', 'banana'))


The above function will construct a nested object based on the paths. If you want to just update an existing object, you could traverse the object and set the value like this:

function set(dataObj, ...paths) {
  let value = paths.pop(),
      nested = dataObj;

  for (let i = 0; i < paths.length; i++) {
    const path = paths[i];

    if (i === paths.length - 1 && nested)
      nested[path] = value; // set the value if it's the final item

    if (path !== null && nested)
      nested = nested[path]; // get another level of nesting
  }

  return dataObj;
}

let obj = { utility: { exportId: 'banana' } }

console.log(set(obj, 'utility', null, null, null, 'exportId', 'orange'))

obj = {
  history: {
    current: {
      fruit: 'apple'
    }
  }
}

console.log(set(obj, 'history', 'current', null, null, 'fruit', 'orange'))

7 Comments

And I use that object as a means to traverse my original data structure?
@mbilyanov sorry, I didn't get you
Because, those keywords are a bit like a map, in a sense the way-points to be followed in order to reach the key that needs to be changed, I was not sure how would I be using the result of the reduce to traverse my original data set. So I guess, I will use it to move down the hierarchy per each key in the result of the reduce for each key in my original data-structure.
@mbilyanov I have updated the code. Not sure if this is what you need though.
Your solution is a good answer to the question. Thanks! One issue though, all the arguments, apart from last two exportId and orange are all nested. I'm trying to fix your code so that we actually walk down the hierarchy, So history', 'current', null, null, 'fruit', 'apple' would be history: { current: { fruit: apple } }
|

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.