Подтвердить что ты не робот

Создание структуры вложенных объектов с помощью строкового ключа/пути

Я хочу создать функцию под названием createAssociativeArray, которая будет восстанавливать два параметра: string и object, например:

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

Последний элемент string должен получить данные object. Пример использования/возврата:

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

// key1: {
//   key2: {
//     key3: {
//       data1: 1,
//       data2: 2,
//       data3: 3
//     }
//   }
// }

Какой самый простой и надежный способ сделать это?

Использовать eval не является возможностью.


Что я пытался:

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

Это не вызвало ожидаемого результата, потому что объект сбрасывается до {}.

[JSFiddle]

4b9b3361

Ответ 1

Вот что я придумал:

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;
}

Ответ 2

Мне было любопытно посмотреть, смогу ли я сделать рекурсивное решение, поэтому вот оно:

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);
}

Рабочая демонстрация JSFiddle: https://jsfiddle.net/pt352dxg/

Ответ 3

Возможная реализация:

Рабочая демонстрация

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;
}

Ответ 4

Эта функция фактически может принять необязательный существующий объект ({k: 2, kk: 3, key1: 4}) и объединить его с заданным json-контуром. например Попробуйте консоль хром-отладчика:

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

напечатает это:

"{"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;
    };

Ответ 5

Вы были довольно близки в своей первоначальной попытке.

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

http://jsfiddle.net/xewoa06t/

Ответ 6

Это сработало для меня:

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});

В принципе, строит объект с нуля, начиная с исходного объекта, затем обертывая "слои" вокруг него рекурсивно

Ответ 7

Хороший случай для рекурсивной функции!

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;
  }
}

Ответ 8

Это проще с помощью простого цикла, ключевой момент делается наоборот (например, @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>')

Ответ 9

Поскольку никто не доказывал решение while -loop:

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;
}