Назначить значение для узла в многомерном массиве JavaScript - PullRequest
0 голосов
/ 14 мая 2011

Я пытаюсь присвоить элементу внутри объекта json новое значение (текст / объект / массив). У меня есть функция подкачки, которая принимает объект json, массив с индексами для получения элемента и значением для его замены. В настоящее время я использую eval, который по некоторым признакам является «злом». Есть ли лучший способ сделать это без Eval или Eval нормально в этом случае? Имейте в виду, что он должен быть динамическим, потому что массив может измениться. Также может быть важно отметить, что я программно создаю параметр массива.

//array looks like: ["cluster", "2", "segment", "0", "node", "3"]    
JsonManager.prototype.swap = function(json, array, val){
        var statement = "json";
        for (var i = 0; i < array.length; i++) {
            if(!isNumeric(array[i]))
            {
            statement += "[\"" + array[i] + "\"]";          
            }else{
                statement += "[" + array[i] + "]"   
            }
        }
        statement += " = val";
        eval(statement);
    };

Пример объекта JSON:

var customers = {
    "cluster": [{
        "clusterid": "cluster1.1",
        "color": "blue",
        "flights": "784",
        "profit": "524125",
        "clv": "2364",
        "segment": [{
            "segmentid": "segment1.1",
            "color": "green",
            "flights": "82",
            "profit": "22150",
            "clv": "1564",
            "node": [{
                "nodeid": "node1.1",
                "color": "orange",
                "xpos": "1",
                "ypos": "1"
            }, {
                "nodeid": "node1.2",
                "color": "blue",
                "xpos": "1",
                "ypos": "2"
            }, {
                "nodeid": "node1.3",
                "color": "orange",
                "xpos": "1",
                "ypos": "3"
            }, {
                "nodeid": "node1.4",
                "color": "orange",
                "xpos": "1",
                "ypos": "4"
            }]
        }, {
            "segmentid": "segment1.2",
            "color": "red",
            "flights": "2",
            "profit": "2150",
            "clv": "1564",
            "node": [{
                "nodeid": "node2.1",
                "color": "tan",
                "xpos": "2",
                "ypos": "1"
            }, {
                "nodeid": "node2.2",
                "color": "tan",
                "xpos": "2",
                "ypos": "2"
            }, {
                "nodeid": "node2.3",
                "color": "tan",
                "xpos": "2",
                "ypos": "3"
            }, {
                "nodeid": "node2.4",
                "color": "tan",
                "xpos": "2",
                "ypos": "4"
            }]
        }]
    }, {
        "clusterid": "cluster1.2",
        "flights": "4",
        "profit": "5245",
        "clv": "2364",
        "segment": [{
            "segmentid": "segment1.2",
            "flights": "2",
            "profit": "2150",
            "clv": "1564",
            "node": [{
                "nodeid": "node3.1",
                "xpos": "3",
                "ypos": "1"
            }, {
                "nodeid": "node3.2",
                "xpos": "3",
                "ypos": "2"
            }, {
                "nodeid": "node3.3",
                "xpos": "3",
                "ypos": "3"
            }, {
                "nodeid": "node3.4",
                "xpos": "3",
                "ypos": "4"
            }]
        }]
    }, {
        "clusterid": "cluster1.3",
        "flights": "10",
        "profit": "456978",
        "clv": "548",
        "segment": [{
            "segmentid": "segment1.3",
            "flights": "2",
            "profit": "2150",
            "clv": "1564",
            "node": [{
                "nodeid": "node4.1",
                "xpos": "4",
                "ypos": "1"
            }, {
                "nodeid": "node4.2",
                "xpos": "4",
                "ypos": "2"
            }, {
                "nodeid": "node4.3",
                "xpos": "4",
                "ypos": "3"
            }, {
                "nodeid": "node4.4",
                "xpos": "4",
                "ypos": "7"
            }]
        }]
    }]
};

Вот мой метод испытаний:

JsonManager.prototype.init = function(){
    var clause = new Clause("nodeid", "node4.4");
    var indexes = this.search(customers, clause);
    this.swap(customers, indexes.reverse(), {"name": "kevin"});
    var test = customers["cluster"][2]["segment"][0]["node"][3];  //hard coded pointer to node4.4
    var breakPoint = "breakpoint";  //Just used as a point to stop the debugger to see test
};

Для дальнейшего использования вот решение, прокомментированное далее:

JsonManager.prototype.swap = function(obj, path, value) {

   //This is the inner function we are recursing into 
   function descend(obj, path) {
    /*This if statement is used to stop the recrusion,
    when we have iterated through all the paths, it returns
    the object above our desired object */
        if (path.length == 0) {
            return obj;
        }
    /*Recurse into the function passing in the top level object and remove
    the top level object from our path*/ 
        return descend(obj[path[0]], path.slice(1));
    }
//Pass in the object and the (path - the last element)
    var node = descend(obj, path.slice(0, -1));
//Get the last node in path, pull it from node and assign the value
    node[path[path.length - 1]] = value;
};

Ответы [ 2 ]

1 голос
/ 14 мая 2011

Нет смысла использовать eval для этого, просто назначьте объект переменной и используйте эту переменную для перехода на каждый уровень:

JsonManager.prototype.swap = function(json, array, val){
  var j = json;
  for (var i = 0; i < array.length - 1; i++) {
    j = j[array[i]];
  }
  j[array[array.length - 1]] = val;
};
1 голос
/ 14 мая 2011

Ваш объект "JSON" является просто объектом JavaScript.Что еще более важно, это дерево, и деревья легче всего пройти с помощью рекурсии.

JsonManager.prototype.swap = function(obj, path, value) {
    function descend(obj, path) {
        if (path.length == 0) {
            return obj;
        }
        return descend(obj[path[0]], path.slice(1));
    }

    var node = descend(obj, path.slice(0, -1));
    node[path[path.length - 1]] = value;
};

slice извлечет кусок из массива.Таким образом, path.slice(1) возвращает path без первого элемента, а path.slice(0, -1) возвращает его без последнего элемента.Это означает, что мы descend переходим ко второму-последнему узлу объекта, затем устанавливаем последний узел, используя обычную запись массива.Самый простой способ обойти это - вручную поработать на бумаге с примером, подобным приведенному выше.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...