13

I want to make a function called createAssociativeArray which will recive two parameters: string and object, like this:

function createAssociativeArray(string, object) { //... } 

The last item of string should get the object data. See an use/return example:

createAssociativeArray('key1.key2.key3', { data1: 1, data2: 2, data3: 3 }); // key1: { // key2: { // key3: { // data1: 1, // data2: 2, // data3: 3 // } // } // } 

What's the most simple and robust method to do it?

Use eval isn't is a possibility.


What I was tried:

function createAssociativeArray(string, object) { string = string.split('.'); return string.reduce(function(_object, _target, i) { _object[_target] = (i + 1 === string.length ? object : {}); return _object; }, {}); } 

It didn't produced the expected result because the object is reseted to {}.

[JSFiddle]

2
  • 1
    Are you trying to implement namespaces? Also, where does the i variable come from? Commented Sep 25, 2015 at 22:25
  • @StefanBaiu, something like... It's a index from reduce (updated). Commented Sep 25, 2015 at 22:28

10 Answers 10

5

Here's what I came up with:

function createAssociativeArray(string, object) { var parts = string.split('.'); var last = parts[parts.length - 1]; var tree = {}; var node = parts.slice(0, -1).reduce(function (memo, current) { return (memo[current] = {}); }, tree); node[last] = object; return tree; } 
Sign up to request clarification or add additional context in comments.

1 Comment

Try this if you want to merge with an exitsing Object (set the value on a JSON path in a given object): stackoverflow.com/a/32791758/2045312
3

I was curious to see if I could make a recursive solution, so here it is:

function createAssociativeArray(string, object) { if (string === "") return object; var stringarr = string.split('.'); var laststr = stringarr.pop(); var newobj = {}; newobj[laststr] = object; return createAssociativeArray(stringarr.join("."), newobj); } 

Working JSFiddle demo: https://jsfiddle.net/pt352dxg/

Comments

2

Possible implementation:

Working demo

function createChain(keys, value) { var obj = {}; var target = obj; keys = keys.split('.'); keys.forEach(function(key, index) { target = target[key] = index === keys.length - 1 ? value : {}; }); target = value; return obj; } 

Comments

2

This function actually can accept an optional existing Object ({k:2, kk: 3, key1: 4}) and merge that with given json path. e.g. Try on chrome debugger console:

JSON.stringify(createAssociativeArray('key1.key2.key3', { data1: 1, data2: 2, data3: 3}, {k:2,kk:3, key1:{}})) 

will print this:

"{"k":2,"kk":3,"key1":{"key2":{"key3":{"data1":1,"data2":2,"data3":3}}}}" 

..

 function createAssociativeArray(key, value, data) { if(!finalData && data) finalData = data; var finalData; if (!data) data = finalData = {}; var keys = key.split('.'); if (keys.length < 2) { data[keys[0]] = value; } else { if (!data[keys[0]]) data[keys[0]] = {}; data = data[keys.shift()]; createAssociativeArray(keys.join("."),value,data); } return finalData; }; 

Comments

2

You were pretty close in your original attempt.

function createAssociativeArray(string, object) { return string.split('.').reverse().reduce(function (inner, key) { var outer = {}; outer[key] = inner; return outer; }, object); } 

http://jsfiddle.net/xewoa06t/

Comments

1

This worked for me:

function createAssociativeArray(string, object){ var array = string.split('.'); var aArray = {}; if(array.length > 1){ aArray[array[array.length - 1]] = object; array.splice(array.length - 1, 1); createAssociativeArray(array.join('.'), aArray) }else{ aArray[array[array.length - 1]] = object; return aArray } }; createAssociativeArray('key1.key2.key3', {data1: 1, data2: 2, data3: 3}); 

Basically, builds object from ground up, starting with the original object, then wrapping the 'layers' around it recursively

Comments

1

Nice case for a recursive function!

function createAssociativeArray(string, object) { if (string.split('.').length == 1) { var outObj = {}; outObj[string] = object; return outObj; } else { var outObj = {}; outObj[string.split('.')[0]] = createAssociativeArray(string.split('.').slice(1).join('.'), object); return outObj; } } 

Comments

0

It's easier with a simple loop, the key point is doing in reverse (like @JustcallmeDrago)

function createAssociativeArray(keys, data) { var temp, keyPart for(keys = keys.split('.'); keys.length; data = temp) { keyPart = keys.pop() temp = {} temp[keyPart] = data } return data } // TEST x = createAssociativeArray("key1.key2.key3", { data1: "value1", data2: "value2" }) document.write('<pre>'+x+'\n'+x.key1 +'\n' +x.key1.key2 + '\n' +x.key1.key2.key3 +'\n' +x.key1.key2.key3.data1 +'\n' +x.key1.key2.key3.data2 +'</pre>')

Comments

0

Since no one have proviced a while-loop solution:

function namespace(path, context) { var obj = context; var s = path.split('.'); var p; while (s.length) { p = s.shift(); obj = obj[p] || (obj[p] = {}); } return context; } 

Comments

0

ES6 one liner

(str, obj) => str.split('.').reverse().reduce((inner, key) => ({[key]: inner}), obj); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.