代码之家  ›  专栏  ›  技术社区  ›  Kashif Richard Brightwell

在Javascript对象中保留未知项计数

  •  3
  • Kashif Richard Brightwell  · 技术社区  · 9 年前

    我正在解析一个数据源,并希望在JS中填充一个对象,结果如下:

    data = {
        "USA":
            {"NY":{"active":5,"inactive":2}},
            {"WA":{"active":16,"inactive":11}},
        "Canada":
            {"NY":{"active":5,"inactive":2}}
    }
    

    一开始,我不知道我将获得数据的国家或州的数量。因此,我开始像这样:

    var data = {}
    

    然后尝试像这样填充数据:

    data["USA"]["NY"]["active"] = data["USA"]["NY"]["active"]++;
    

    但它不起作用。

    4 回复  |  直到 9 年前
        1
  •  2
  •   Nina Scholz    9 年前

    您需要对对象的每个级别进行检查,如果未设置,则将对象作为默认值,或将数字设为零。

    var data = {};
    
    data["USA"] = data["USA"] || {};
    data["USA"]["NY"] = data["USA"]["NY"] || {};
    data["USA"]["NY"]["active"] = data["USA"]["NY"]["active"] || 0;
    data["USA"]["NY"]["active"]++;
    
    console.log(data);

    更好的方法是使用一个函数来检查和创建默认对象

    function getValue(o, path) {
        return path.reduce(function (o, k) {
            return (o || {})[k];
        }, o);
    }
    
    function setValue(object, path, value) {
        var way = path.slice(),
            last = way.pop();
    
        way.reduce(function (r, a) {
            return r[a] = r[a] || {};
        }, object)[last] = value;
    }
    
    function increment(object, path, value) {
        setValue(data, path, (getValue(data, path) || 0 ) + (value || 1));
    }
    
    var data = {};
    increment(data, ['USA', 'NY', 'active'], 1);
    
    console.log(data);
        2
  •  1
  •   alek kowalczyk    9 年前

    不能以这种方式动态创建对象属性。因此,您正在正确创建数据对象:

    var data = {}
    

    但下一行是错误的,因为:

    data["USA"] 此时未定义,因此无法访问 ["NY"] 属于 undefined ,这将引发异常。因此,您不仅需要初始化根 data 对象,还需要为该对象的每个属性初始化一个对象。

    你可以按字面意思做:

    if(!data["USA"]) 
        data["USA"] = {};
    

    或使用 || 操作员,将分配给 数据[“美国”] 如果存在相同的对象(因此它基本上没有任何作用),或者它将创建一个新对象:

    data["USA"] = data["USA"] || {};
    

    现在,您需要为无法访问的每个对象执行此逻辑。因此,使用较短的语法:

    data["USA"] = data["USA"] || {};
    data["USA"]["NY"] = data["USA"]["NY"] || {};
    data["USA"]["NY"]["active"] = data["USA"]["NY"]["active"] || 0; 
    

    之后,对象结构准备好了,请记住 ++ 是一个返回数字的运算符,然后将该数字加1。

    因此:

    data["USA"]["NY"]["active"] = data["USA"]["NY"]["active"]++;
    

    不会更改号码,您必须执行以下任一操作:

    data["USA"]["NY"]["active"]++;
    

    或:

    data["USA"]["NY"]["active"] = data["USA"]["NY"]["active"]+1;
    
        3
  •  0
  •   Quentin    9 年前
    data["USA"]["NY"]["active"] = data["USA"]["NY"]["active"]++;
    

    你是:

    1. 重视 data["USA"]["NY"]["active"] (这是2)
    2. 递增 数据〔“美国”〕〔“纽约”〕【“活跃”〕 (现在是3)
    3. 将(2)的值赋值给 数据〔“美国”〕〔“纽约”〕【“活跃”〕 (有效地逆转了上一步的效果)

    如果要增加该值,请执行以下操作:

    data["USA"]["NY"]["active"]++;
    

    只是那个,除了那个什么都没有。

        4
  •  0
  •   Nenad Vracar    9 年前

    您可以使用创建自己的函数 reduce() 它可以将字符串作为嵌套对象键,并构建深层对象结构。

    var data = {}
    
    function add(str) {
      var arr = str.split('.')
      return arr.reduce(function(r, e, i) {
        return arr.length - 1 != i ? r[e] || (r[e] = {}) : r[e] = (r[e] || 0) + 1
      }, data)
    }
    
    add('USA.NY.active')
    add('USA.NY.active')
    add('USA.NY.inactive')
    add('Canada.NY.active')
    console.log(data)