Creating nested objects from string

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
3
down vote

favorite












I implemented a method, to create an object based on a series of strings that are passed to it, of any depth or length. The way I implemented the solution was to map over the arguments. Assuming that strings are passed in the form x.a, it then splits the string by the '.', returning just a single object with that key if the array only had one element otherwise, it was passed through a reducer to produce an array of objects which would then be merged into one object.



I'd like to make this better/ are there any concerns with using a reducer in a map function, since it's on the order of O(n2)?



type TKeys = string
type TTarget =
[key: string]: TTarget
type TTemplate =
target: TTarget,
props: ReadonlyArray<string>

interface ITemplate
target: TTemplate["target"]
,
props: ReadonlyArray<string>

const createObject = <T>(...keys: TKeys): T => (
keys.map(key =>
const props = key.split('.');
const reducerTemplate: ITemplate =
target: ,
props: ['']


return props.length < 2
?
[key]: ''

: props.reduce((obj: ITemplate, prop: string) =>
const target: ITemplate["target"] = obj.target
if (obj.props.length === 0)
console.log(obj, prop);
obj.props = [prop];
target[prop] = ;
return obj;

const object: ITemplate["target"] = obj
.props
.reduce((prev: TTemplate["target"] , next: string) => (target[next] , reducerTemplate)
).reduce((main: | TTarget, obj: TTarget ): TTarget => (
...main,
...obj
), ))


Example Usage:



createObject('a.b.c.d', 'hello.world', 'test') 
//outputs

a:
b:
c:
d: '',
,
,
,
hello:
world: '',
,
test: '',

createObject('hello')
//outputs
hello: ''
createObject('a.b')
//outputs

a:
b: '',
,
;






share|improve this question





















  • Can you post some example input and output? It would make it a lot easier to understand.
    – Máté Safranka
    Jun 4 at 22:11










  • Typescript chokes on this as soon as I paste it into any playground I'm familiar with, even ignoring the compiler errors, the code itself doesn't seem to work. Cannot set property 'a' of undefined given your first example.
    – Gerrit0
    Jun 6 at 1:25
















up vote
3
down vote

favorite












I implemented a method, to create an object based on a series of strings that are passed to it, of any depth or length. The way I implemented the solution was to map over the arguments. Assuming that strings are passed in the form x.a, it then splits the string by the '.', returning just a single object with that key if the array only had one element otherwise, it was passed through a reducer to produce an array of objects which would then be merged into one object.



I'd like to make this better/ are there any concerns with using a reducer in a map function, since it's on the order of O(n2)?



type TKeys = string
type TTarget =
[key: string]: TTarget
type TTemplate =
target: TTarget,
props: ReadonlyArray<string>

interface ITemplate
target: TTemplate["target"]
,
props: ReadonlyArray<string>

const createObject = <T>(...keys: TKeys): T => (
keys.map(key =>
const props = key.split('.');
const reducerTemplate: ITemplate =
target: ,
props: ['']


return props.length < 2
?
[key]: ''

: props.reduce((obj: ITemplate, prop: string) =>
const target: ITemplate["target"] = obj.target
if (obj.props.length === 0)
console.log(obj, prop);
obj.props = [prop];
target[prop] = ;
return obj;

const object: ITemplate["target"] = obj
.props
.reduce((prev: TTemplate["target"] , next: string) => (target[next] , reducerTemplate)
).reduce((main: | TTarget, obj: TTarget ): TTarget => (
...main,
...obj
), ))


Example Usage:



createObject('a.b.c.d', 'hello.world', 'test') 
//outputs

a:
b:
c:
d: '',
,
,
,
hello:
world: '',
,
test: '',

createObject('hello')
//outputs
hello: ''
createObject('a.b')
//outputs

a:
b: '',
,
;






share|improve this question





















  • Can you post some example input and output? It would make it a lot easier to understand.
    – Máté Safranka
    Jun 4 at 22:11










  • Typescript chokes on this as soon as I paste it into any playground I'm familiar with, even ignoring the compiler errors, the code itself doesn't seem to work. Cannot set property 'a' of undefined given your first example.
    – Gerrit0
    Jun 6 at 1:25












up vote
3
down vote

favorite









up vote
3
down vote

favorite











I implemented a method, to create an object based on a series of strings that are passed to it, of any depth or length. The way I implemented the solution was to map over the arguments. Assuming that strings are passed in the form x.a, it then splits the string by the '.', returning just a single object with that key if the array only had one element otherwise, it was passed through a reducer to produce an array of objects which would then be merged into one object.



I'd like to make this better/ are there any concerns with using a reducer in a map function, since it's on the order of O(n2)?



type TKeys = string
type TTarget =
[key: string]: TTarget
type TTemplate =
target: TTarget,
props: ReadonlyArray<string>

interface ITemplate
target: TTemplate["target"]
,
props: ReadonlyArray<string>

const createObject = <T>(...keys: TKeys): T => (
keys.map(key =>
const props = key.split('.');
const reducerTemplate: ITemplate =
target: ,
props: ['']


return props.length < 2
?
[key]: ''

: props.reduce((obj: ITemplate, prop: string) =>
const target: ITemplate["target"] = obj.target
if (obj.props.length === 0)
console.log(obj, prop);
obj.props = [prop];
target[prop] = ;
return obj;

const object: ITemplate["target"] = obj
.props
.reduce((prev: TTemplate["target"] , next: string) => (target[next] , reducerTemplate)
).reduce((main: | TTarget, obj: TTarget ): TTarget => (
...main,
...obj
), ))


Example Usage:



createObject('a.b.c.d', 'hello.world', 'test') 
//outputs

a:
b:
c:
d: '',
,
,
,
hello:
world: '',
,
test: '',

createObject('hello')
//outputs
hello: ''
createObject('a.b')
//outputs

a:
b: '',
,
;






share|improve this question













I implemented a method, to create an object based on a series of strings that are passed to it, of any depth or length. The way I implemented the solution was to map over the arguments. Assuming that strings are passed in the form x.a, it then splits the string by the '.', returning just a single object with that key if the array only had one element otherwise, it was passed through a reducer to produce an array of objects which would then be merged into one object.



I'd like to make this better/ are there any concerns with using a reducer in a map function, since it's on the order of O(n2)?



type TKeys = string
type TTarget =
[key: string]: TTarget
type TTemplate =
target: TTarget,
props: ReadonlyArray<string>

interface ITemplate
target: TTemplate["target"]
,
props: ReadonlyArray<string>

const createObject = <T>(...keys: TKeys): T => (
keys.map(key =>
const props = key.split('.');
const reducerTemplate: ITemplate =
target: ,
props: ['']


return props.length < 2
?
[key]: ''

: props.reduce((obj: ITemplate, prop: string) =>
const target: ITemplate["target"] = obj.target
if (obj.props.length === 0)
console.log(obj, prop);
obj.props = [prop];
target[prop] = ;
return obj;

const object: ITemplate["target"] = obj
.props
.reduce((prev: TTemplate["target"] , next: string) => (target[next] , reducerTemplate)
).reduce((main: | TTarget, obj: TTarget ): TTarget => (
...main,
...obj
), ))


Example Usage:



createObject('a.b.c.d', 'hello.world', 'test') 
//outputs

a:
b:
c:
d: '',
,
,
,
hello:
world: '',
,
test: '',

createObject('hello')
//outputs
hello: ''
createObject('a.b')
//outputs

a:
b: '',
,
;








share|improve this question












share|improve this question




share|improve this question








edited Jun 4 at 23:53
























asked Jun 4 at 19:58









user3655510

162




162











  • Can you post some example input and output? It would make it a lot easier to understand.
    – Máté Safranka
    Jun 4 at 22:11










  • Typescript chokes on this as soon as I paste it into any playground I'm familiar with, even ignoring the compiler errors, the code itself doesn't seem to work. Cannot set property 'a' of undefined given your first example.
    – Gerrit0
    Jun 6 at 1:25
















  • Can you post some example input and output? It would make it a lot easier to understand.
    – Máté Safranka
    Jun 4 at 22:11










  • Typescript chokes on this as soon as I paste it into any playground I'm familiar with, even ignoring the compiler errors, the code itself doesn't seem to work. Cannot set property 'a' of undefined given your first example.
    – Gerrit0
    Jun 6 at 1:25















Can you post some example input and output? It would make it a lot easier to understand.
– Máté Safranka
Jun 4 at 22:11




Can you post some example input and output? It would make it a lot easier to understand.
– Máté Safranka
Jun 4 at 22:11












Typescript chokes on this as soon as I paste it into any playground I'm familiar with, even ignoring the compiler errors, the code itself doesn't seem to work. Cannot set property 'a' of undefined given your first example.
– Gerrit0
Jun 6 at 1:25




Typescript chokes on this as soon as I paste it into any playground I'm familiar with, even ignoring the compiler errors, the code itself doesn't seem to work. Cannot set property 'a' of undefined given your first example.
– Gerrit0
Jun 6 at 1:25










2 Answers
2






active

oldest

votes

















up vote
0
down vote













I think a plain loop works better here. I don't know TypeScript unfortunately, but I'm pretty sure you can adapt this easily enough:



function createObject(...keys) 
let obj = ;
for (let key of keys)
let putInto = obj;
let tokens = key.split('.');
for (let i = 0; i < tokens.length; i++) value;
putInto = putInto[name];


return obj;






share|improve this answer




























    up vote
    0
    down vote













    In general case this always maps to O(n2). You may introduce some complex optimisations but this yields to long hardly readable code. Are you sure you will benefit from this?



    I am a huge fan of CoffeeScript language and both CoffeeScript and TypeScript do a lot of hidden work so it is crucial to see the compiled JavaScript. Also, if your primary concearn is perfomance you will benefit greatly from plain JavaScript solution.



    So here is my attempt on it. It is simular to Máté Safranka solution (which is quite nice and readable). It uses Array.prototype.reduce to remove all local variables in favor of function arguments:






    function createObject(...pathes) 
    return pathes.reduce(function (obj, path)
    path.split('.').reduce((obj, key) => obj[key] = obj[key] , );


    // Some tests
    console.log(createObject('a.b.c.d', 'hello.world', 'test'));
    console.log(createObject('a', 'a.b', 'a.b.c'));
    console.log(createObject());
    console.log(createObject('')); // note: not handled properly





    The last one is not handled properly, but to me it looks more like an invalid input.



    Tests



    I've added provided solutions to jsperf test and compiled your TypeScript at Playground but for some reason it doesn't work as intended.



    So, here is the benchmark. FYI check results in different browsers.






    share|improve this answer





















      Your Answer




      StackExchange.ifUsing("editor", function ()
      return StackExchange.using("mathjaxEditing", function ()
      StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
      StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
      );
      );
      , "mathjax-editing");

      StackExchange.ifUsing("editor", function ()
      StackExchange.using("externalEditor", function ()
      StackExchange.using("snippets", function ()
      StackExchange.snippets.init();
      );
      );
      , "code-snippets");

      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "196"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      convertImagesToLinks: false,
      noModals: false,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: null,
      bindNavPrevention: true,
      postfix: "",
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );








       

      draft saved


      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f195838%2fcreating-nested-objects-from-string%23new-answer', 'question_page');

      );

      Post as a guest






























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      0
      down vote













      I think a plain loop works better here. I don't know TypeScript unfortunately, but I'm pretty sure you can adapt this easily enough:



      function createObject(...keys) 
      let obj = ;
      for (let key of keys)
      let putInto = obj;
      let tokens = key.split('.');
      for (let i = 0; i < tokens.length; i++) value;
      putInto = putInto[name];


      return obj;






      share|improve this answer

























        up vote
        0
        down vote













        I think a plain loop works better here. I don't know TypeScript unfortunately, but I'm pretty sure you can adapt this easily enough:



        function createObject(...keys) 
        let obj = ;
        for (let key of keys)
        let putInto = obj;
        let tokens = key.split('.');
        for (let i = 0; i < tokens.length; i++) value;
        putInto = putInto[name];


        return obj;






        share|improve this answer























          up vote
          0
          down vote










          up vote
          0
          down vote









          I think a plain loop works better here. I don't know TypeScript unfortunately, but I'm pretty sure you can adapt this easily enough:



          function createObject(...keys) 
          let obj = ;
          for (let key of keys)
          let putInto = obj;
          let tokens = key.split('.');
          for (let i = 0; i < tokens.length; i++) value;
          putInto = putInto[name];


          return obj;






          share|improve this answer













          I think a plain loop works better here. I don't know TypeScript unfortunately, but I'm pretty sure you can adapt this easily enough:



          function createObject(...keys) 
          let obj = ;
          for (let key of keys)
          let putInto = obj;
          let tokens = key.split('.');
          for (let i = 0; i < tokens.length; i++) value;
          putInto = putInto[name];


          return obj;







          share|improve this answer













          share|improve this answer



          share|improve this answer











          answered Jun 5 at 10:16









          Máté Safranka

          3315




          3315






















              up vote
              0
              down vote













              In general case this always maps to O(n2). You may introduce some complex optimisations but this yields to long hardly readable code. Are you sure you will benefit from this?



              I am a huge fan of CoffeeScript language and both CoffeeScript and TypeScript do a lot of hidden work so it is crucial to see the compiled JavaScript. Also, if your primary concearn is perfomance you will benefit greatly from plain JavaScript solution.



              So here is my attempt on it. It is simular to Máté Safranka solution (which is quite nice and readable). It uses Array.prototype.reduce to remove all local variables in favor of function arguments:






              function createObject(...pathes) 
              return pathes.reduce(function (obj, path)
              path.split('.').reduce((obj, key) => obj[key] = obj[key] , );


              // Some tests
              console.log(createObject('a.b.c.d', 'hello.world', 'test'));
              console.log(createObject('a', 'a.b', 'a.b.c'));
              console.log(createObject());
              console.log(createObject('')); // note: not handled properly





              The last one is not handled properly, but to me it looks more like an invalid input.



              Tests



              I've added provided solutions to jsperf test and compiled your TypeScript at Playground but for some reason it doesn't work as intended.



              So, here is the benchmark. FYI check results in different browsers.






              share|improve this answer

























                up vote
                0
                down vote













                In general case this always maps to O(n2). You may introduce some complex optimisations but this yields to long hardly readable code. Are you sure you will benefit from this?



                I am a huge fan of CoffeeScript language and both CoffeeScript and TypeScript do a lot of hidden work so it is crucial to see the compiled JavaScript. Also, if your primary concearn is perfomance you will benefit greatly from plain JavaScript solution.



                So here is my attempt on it. It is simular to Máté Safranka solution (which is quite nice and readable). It uses Array.prototype.reduce to remove all local variables in favor of function arguments:






                function createObject(...pathes) 
                return pathes.reduce(function (obj, path)
                path.split('.').reduce((obj, key) => obj[key] = obj[key] , );


                // Some tests
                console.log(createObject('a.b.c.d', 'hello.world', 'test'));
                console.log(createObject('a', 'a.b', 'a.b.c'));
                console.log(createObject());
                console.log(createObject('')); // note: not handled properly





                The last one is not handled properly, but to me it looks more like an invalid input.



                Tests



                I've added provided solutions to jsperf test and compiled your TypeScript at Playground but for some reason it doesn't work as intended.



                So, here is the benchmark. FYI check results in different browsers.






                share|improve this answer























                  up vote
                  0
                  down vote










                  up vote
                  0
                  down vote









                  In general case this always maps to O(n2). You may introduce some complex optimisations but this yields to long hardly readable code. Are you sure you will benefit from this?



                  I am a huge fan of CoffeeScript language and both CoffeeScript and TypeScript do a lot of hidden work so it is crucial to see the compiled JavaScript. Also, if your primary concearn is perfomance you will benefit greatly from plain JavaScript solution.



                  So here is my attempt on it. It is simular to Máté Safranka solution (which is quite nice and readable). It uses Array.prototype.reduce to remove all local variables in favor of function arguments:






                  function createObject(...pathes) 
                  return pathes.reduce(function (obj, path)
                  path.split('.').reduce((obj, key) => obj[key] = obj[key] , );


                  // Some tests
                  console.log(createObject('a.b.c.d', 'hello.world', 'test'));
                  console.log(createObject('a', 'a.b', 'a.b.c'));
                  console.log(createObject());
                  console.log(createObject('')); // note: not handled properly





                  The last one is not handled properly, but to me it looks more like an invalid input.



                  Tests



                  I've added provided solutions to jsperf test and compiled your TypeScript at Playground but for some reason it doesn't work as intended.



                  So, here is the benchmark. FYI check results in different browsers.






                  share|improve this answer













                  In general case this always maps to O(n2). You may introduce some complex optimisations but this yields to long hardly readable code. Are you sure you will benefit from this?



                  I am a huge fan of CoffeeScript language and both CoffeeScript and TypeScript do a lot of hidden work so it is crucial to see the compiled JavaScript. Also, if your primary concearn is perfomance you will benefit greatly from plain JavaScript solution.



                  So here is my attempt on it. It is simular to Máté Safranka solution (which is quite nice and readable). It uses Array.prototype.reduce to remove all local variables in favor of function arguments:






                  function createObject(...pathes) 
                  return pathes.reduce(function (obj, path)
                  path.split('.').reduce((obj, key) => obj[key] = obj[key] , );


                  // Some tests
                  console.log(createObject('a.b.c.d', 'hello.world', 'test'));
                  console.log(createObject('a', 'a.b', 'a.b.c'));
                  console.log(createObject());
                  console.log(createObject('')); // note: not handled properly





                  The last one is not handled properly, but to me it looks more like an invalid input.



                  Tests



                  I've added provided solutions to jsperf test and compiled your TypeScript at Playground but for some reason it doesn't work as intended.



                  So, here is the benchmark. FYI check results in different browsers.






                  function createObject(...pathes) 
                  return pathes.reduce(function (obj, path)
                  path.split('.').reduce((obj, key) => obj[key] = obj[key] , );


                  // Some tests
                  console.log(createObject('a.b.c.d', 'hello.world', 'test'));
                  console.log(createObject('a', 'a.b', 'a.b.c'));
                  console.log(createObject());
                  console.log(createObject('')); // note: not handled properly





                  function createObject(...pathes) 
                  return pathes.reduce(function (obj, path)
                  path.split('.').reduce((obj, key) => obj[key] = obj[key] , );


                  // Some tests
                  console.log(createObject('a.b.c.d', 'hello.world', 'test'));
                  console.log(createObject('a', 'a.b', 'a.b.c'));
                  console.log(createObject());
                  console.log(createObject('')); // note: not handled properly






                  share|improve this answer













                  share|improve this answer



                  share|improve this answer











                  answered Jul 21 at 15:10









                  sineemore

                  1,173217




                  1,173217






















                       

                      draft saved


                      draft discarded


























                       


                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f195838%2fcreating-nested-objects-from-string%23new-answer', 'question_page');

                      );

                      Post as a guest













































































                      Popular posts from this blog

                      Greedy Best First Search implementation in Rust

                      Function to Return a JSON Like Objects Using VBA Collections and Arrays

                      C++11 CLH Lock Implementation