【问题标题】:Dynamically generating json property value动态生成json属性值
【发布时间】:2014-10-18 06:56:31
【问题描述】:

我有一个json对象如下:

{
    "critiquesAvg": 4.75: , 
    "critiques":[
        {
            'author': 'John Does',
            'comment': "I like it",
            'stars' : 5
        },
        {
            'author': 'Jacob Works',
            'comment': "I like it too",
            'stars' : 4.5
        }
    ]
}

我需要通过平均 critiques 数组的 stars 属性值来动态计算 critiquesAvg 的值 (4.75)。

有人可以帮我吗?

编辑: 抱歉,我遇到的实际问题如下:

var dealers = [{
    "id", 1874
    "critiquesAvg": 4.75 ,
    "critiques":[
        {
            'author': 'John Does',
            'comment': "I like it",
            'stars' : 5
        },
        {
            'author': 'Jacob Works',
            'comment': "I like it too",
            'stars' : 4.5
        }
    ]
},
{
    "id": 1345,
    "critiquesAvg": 5 ,
    "critiques":[
        {
            'author': 'John Does',
            'comment': "I like it",
            'stars' : 5
        },
        {
            'author': 'Jacob Works',
            'comment': "I like it too",
            'stars' : 5
        }
    ]
}
];

在这里,我想根据特定经销商数据的平均评论数动态计算 critiquesAvg 属性的值。

【问题讨论】:

  • 使用Object.defineProperty函数重新定义属性critiquesAvg怎么样?
  • 我没有得到你想要的,你能举个例子吗?
  • @Mritunjay:只是想将critiquesAvg 的值4.75 设为data.critiquesAvg,并根据critiques 数组中的批评对象数量动态计算critiquesAvg

标签: javascript arrays json dynamic


【解决方案1】:

我会为此使用reduce(小提琴here):

var data = {
    "critiquesAvg": 4.75, 
    "critiques":[
        {
            'author': 'John Does',
            'comment': "I like it",
            'stars' : 5
        },
        {
            'author': 'Jacob Works',
            'comment': "I like it too",
            'stars' : 4.5
        }
    ]
};

var sum = data.critiques.reduce(function(x, y) { return x.stars + y.stars });
var average = sum / data.critiques.length;

data.critiquesAvg = average;

至于更新的问题,您需要添加一个额外的循环,例如使用forEach(更新的小提琴here):

dealers.forEach(function(data) {
    var sum = data.critiques.reduce(function(x, y) { return x.stars + y.stars });
    var average = sum / data.critiques.length;

    data.critiquesAvg = average;
});

【讨论】:

  • 您好 Robby 感谢您的回复,我已经稍微编辑了我的问题,请您再看一下,看看是否有解决方案?谢谢。
  • @JyotiPuri Chrome(是)、Firefox(自 1.5 起)、IE(自 9 起)、Safari(是)、Opera(是)。你打算用什么浏览器?
【解决方案2】:

您可以通过以下函数替换 critiquesAvg 来做到这一点:

critiquesAvg: function(){
    var stars = 0;
    for(i=0;i<this.critiques.length;i++) {
        stars +=this.critiques[i].stars;
    }
    return stars/this.critiques.length
}, 

检查 script.js 这个插件: http://plnkr.co/edit/dDxkZxKxvq0HRppASnzR?p=preview

【讨论】:

  • @Jyoti:我刚刚修改了原始问题。你能看看它的编辑部分吗?谢谢。
  • 这不再是 JSON。
【解决方案3】:

向您的对象添加一个初始化函数,并在其中进行所有计算。 如果您查看其他面向对象的语言,通常您会在构造函数中进行此类计算。类似地,您可以使用自定义方法实现相同的目的,该方法将充当构造函数并设置初始状态 你的对象。

var obj = ({
  "critiquesAvg": 0, //start with zero and init function will calculate the actual avg
  "critiques": [{
    'author': 'John Does',
    'comment': "I like it",
    'stars': 5
  }, {
    'author': 'Jacob Works',
    'comment': "I like it too",
    'stars': 4.5
  }],
  init: function() {
    var result = this.critiques.reduce(function(prev, current, idx, arr) {
      return prev['stars'] + current['stars'];
    });
    this.critiquesAvg = result / this.critiques.length;
    return this;
  }
}).init(); // you are invoking the init method inline here (coding pattern)
           // also watch out for the ( ) around the object literal. 
           // this is what makes the method on the object invokable inline.

这是一种编码模式,通常用于设置对象状态(尤其是当您在 javascript 中使用对象字面量语法时)。

DEMO

更新答案

遵循相同的模式,但不是每个都有一个 init 方法,而是一个通用的初始化方法会执行相同的操作。

var initialize = function() {
  var result = this.critiques.reduce(function(prev, current, idx, arr) {
    return prev['stars'] + current['stars'];
  });
  this.critiquesAvg = result / this.critiques.length;
  return this;
};

var dealers = [({
  "id": 1874,
  "critiquesAvg": 0,
  "critiques": [{
    'author': 'John Does',
    'comment': "I like it",
    'stars': 5
  }, {
    'author': 'Jacob Works',
    'comment': "I like it too",
    'stars': 4.5
  }],
  init: initialize
}).init(), ({
  "id": 1345,
  "critiquesAvg": 0,
  "critiques": [{
    'author': 'John Does',
    'comment': "I like it",
    'stars': 5
  }, {
    'author': 'Jacob Works',
    'comment': "I like it too",
    'stars': 5
  }],
  init: initialize
}).init()];

DEMO

【讨论】:

  • 谢谢你,真是好东西。我能否请您再次查看问题的已编辑部分,看看是否有 DRY 解决方案。
  • 谢谢BOSS,东西真干净:)
【解决方案4】:

Robby 做到了,我想我会把它扩展成一个函数

function dataGen(data){
    //so we do not overwrite data globally as objects are references
    var data = data;
    var sum = data.critiques.reduce(function(x, y) {
        return x.stars + y.stars 
    });
    var average = sum / data.critiques.length;

    data.critiquesAvg = average;
    return data;
}

var data = { 
    "critiques":[
        {
            'author': 'John Does',
            'comment': "I like it",
            'stars' : 5
        },
        {
            'author': 'Jacob Works',
            'comment': "I like it too",
            'stars' : 4.5
        }
    ]
};

data.critiques.push({
    'author': 'Wacob Works',
    'comment': "I like it too",
    'stars' : 3.5
});

data = dataGen(data);

好的,很好地更新了您的要求,希望这有助于http://jsbin.com/sevor/1/edit

var dealers = [{
  "id": 1874,
    "critiquesAvg": 0 ,
    "critiques":[
        {
            'author': 'John Does',
            'comment': "I like it",
            'stars' : 5
        },
        {
            'author': 'Jacob Works',
            'comment': "I like it too",
            'stars' : 4.5
        }
    ]
},
{
    "id": 1345,
    "critiquesAvg": 5 ,
    "critiques":[
        {
            'author': 'John Does',
            'comment': "I like it",
            'stars' : 5
        },
        {
            'author': 'Jacob Works',
            'comment': "I like it too",
            'stars' : 5
        }
    ]
}
];

var Dealers = {
    calculate: function(dealer){
        var sum = dealer.critiques.reduce(function(x, y) {
            return x.stars + y.stars; 
        });
        var average = sum / dealer.critiques.length;
        return average;
    },
    gen: function(dealers){
        for(i=0;i<dealers.length;i++){
            dealers[i].critiquesAvg = this.calculate(dealers[i]);
        }

        return dealers;
    }
};

dealers = Dealers.gen(dealers);

dealers.push({
    "id": 1346,
    "critiquesAvg": 0 ,
    "critiques":[
        {
            'author': 'John Does',
            'comment': "I like it",
            'stars' : 5
        },
        {
            'author': 'Jacob Works',
            'comment': "I like it too",
            'stars' : 5
        }
    ]
});

dealers = Dealers.gen(dealers);
console.log(dealers);

【讨论】:

  • 您能否再看一下问题的编辑部分,看看是否有解决方案?当我获得经销商的 json 数据时,我希望根据特定经销商的 critiques 自动生成 critiqueAvg 值。谢谢。
猜你喜欢
  • 1970-01-01
  • 2014-12-22
  • 1970-01-01
  • 2021-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-02
  • 2021-07-28
相关资源
最近更新 更多