воскресенье, 24 февраля 2013 г.

Javascript. Установка и чтение данных в многомерных хэшах

Задача: имеем хэш в js. Требуется установить значение по любой цепочке вложенности, используя вызов всего одной функции. И, используя вызов одной функции, прочесть значение.


То есть, имея хэш

var example = {
a: {
b: {
c: 'value '
}
}
}

Хотелось бы добавить еще одно значение, тем самым, получив следующий вид:
var example = {
a: {
b: {
c: 'value '
},
d: {
e: 'value2'
}
}
}
И затем прочесть эти значения. При этом не заботясь о существовании промежуточных ключах.

Для этих нужд написал 2 функции. В их реализации отталкивался от кохановского метода Arr::path

Функция setPath.
  • Первым аргументом принимает непосредственно хэш.
  • Вторым - путь по ключам. Может быть задан строкой, где ключи разделены каким-либо символом (или группой симовлов). В данной функции используется точка. Так же это может быть массив, в котором перечисленны ключи в порядке их следования. 
  • Третий аргумент - устанавливаемое значение.
function setPath (o, path, value) {
    if (path) {
        if (typeof path === 'string') {
            path = path.split('.');
        }
        var key = path.shift();
        if (key && key != '') {
            if (path.length) {
                if (!o[key]) {
                    o[key] = {};
                }
                o[key] = setPath(o[key], path, value);
            }
            else {
                o[key] = value;
            }
        }
    }
    return o;
}
Если какой-либо ключ отсутствовал в хэше - он будет создан. Если в не указать значение, то будет установленно undefined вместо него.

Функция getPath. Аргументы полностью идентичны первым двум аргументам предыдущей функции.

function getPath (o, path) {
    var value = o;
    if (path) {
        if (typeof path === 'string') {
            path = path.split('.');
        }
        for (var i = 0; i < path.length; i ++) {
            if (value) {
                value = value[path[i]];
            }
        }
    }
    return value;
}
С приведенным выше примером функции можно использовать так:

Добавим значение 'value2': 
setPath(example, ['a', 'd', 'e'], 'value2');
 Прочтем значение 'value2':
getPath(example, 'a.d.e');