根据多个过滤器计算json数据的平均值

时间:2017-01-27 19:36:41

标签: javascript json

我有一个json数组,如下所示。

var dataObject=[ 
{ "SupplierName" : "John", "Category " : "A", "Points" : 3 },
{ "SupplierName" : "John", "Category " : "A", "Points" : 11 },
{ "SupplierName" : "John", "Category " : "A", "Points" :  },
{ "SupplierName" : "John", "Category " : "B", "Points" : 2 },
{ "SupplierName" : "John", "Category " : "B", "Points" : 6 },
{ "SupplierName" : "Praveen", "Category " : "A", "Points" : 3 },
{ "SupplierName" : "Praveen", "Category " : "A", "Points" : 7 } 
];

我想找到平均值并以下面的格式创建json。如果任何SupplierName的Points为空,则应从平均计算中排除。

var result=[ 
{ "SupplierName" : "John", "Category " : "A",  "Points" : 14, "Average" : 7 },
{ "SupplierName" : "John", "Category " : "B", "Points" : 8, "Average" : 4 },
{ "SupplierName" : "Praveen", "Category " : "A", "Points" : 10, "Average" : 5 } 
];

我尝试了以下代码,但它是基于SupplierName进行过滤的。我不确定如何基于多个值进行过滤。感谢您是否可以指导我。

var count=0;
var avg=0;
var result = dataObject.reduce(function(res, obj) {
    if (!(obj.SupplierName in res)){
            count=0;
        avg=0;
        res.__array.push(res[obj.SupplierName] = obj);
        count++;
        }
    else {
        res[obj.SupplierName].Points += obj.Points;        
        count++;
        res[obj.SupplierName].Points =res[obj.SupplierName].Points;
        avg=res[obj.SupplierName].Points/count;     
        res[obj.SupplierName].Average =avg;
    }
    return res;
}, {__array:[]}).__array
            .sort(function(a,b) { return b.SupplierName - a.SupplierName; });
alert(JSON.stringify(result));

5 个答案:

答案 0 :(得分:2)

使用Array.prototype.reduce()Object.keys()函数的解决方案:

var dataObject = [{ SupplierName: "John", Category: "A", Points: 3 }, { SupplierName: "John", Category: "A", Points: 11 }, { SupplierName: "John", Category: "A", Points: null }, { SupplierName: "John", Category: "B", Points: 2 }, { SupplierName: "John", Category: "B", Points: 6 }, { SupplierName: "Praveen", Category: "A", Points: 3 }, { SupplierName: "Praveen", Category: "A", Points: 7 }],
    
    groups = dataObject.reduce(function (r, o) {
        var k = o.SupplierName + o.Category;
        if (r[k]) {
            if (o.Points) (r[k].Points += o.Points) && ++r[k].Average;
        } else {
           r[k] = o; 
           r[k].Average = 1; // taking 'Average' attribute as an items counter(on the first phase)
        }
        return r;
    }, {});
    
// getting "average of Points"    
var result = Object.keys(groups).map(function (k) {
    groups[k].Average = Math.round(groups[k].Points/groups[k].Average);
    return groups[k];
});    
    
console.log(result);

答案 1 :(得分:0)

var array=[
{ SupplierName : "John", Category : "A", Points : 3 },
{ SupplierName : "John", Category: "A", Points : 5 },
 { SupplierName : "Jennie", Category : "A", Points : 3 },
{ SupplierName : "Jennie", Category: "A", Points : 5 },
];
console.log(array);

//add missing vars
array.forEach(function(elem){
elem["counter"]=1;
elem["Average"]=elem["Points"];
});

//loop trough + join

array.forEach(function(el1){
  array.forEach(function(el2,i2){
     if(el1===el2){return;}
     if(el1.SupplierName===el2.SupplierName && el1.Category===el2.Category){
            el1.counter+=el2.counter;
            el1.Average+=el2.Average;
            console.log("joined",el1,el2);
            delete array[i2];
     }
  });
});


//calculate Average

array.forEach(function(el){
 el.Average=el.Average/el.counter;
});
console.log(array); 

编辑:缩短代码:http://jsbin.com/loqovenocu/1/edit?console

答案 2 :(得分:0)

您可以使用哈希表并构建新数组。



var dataObject = [{ SupplierName: "John", Category: "A", Points: 3 }, { SupplierName: "John", Category: "A", Points: 11 }, { SupplierName: "John", Category: "A", Points: null }, { SupplierName: "John", Category: "B", Points: 2 }, { SupplierName: "John", Category: "B", Points: 6 }, { SupplierName: "Praveen", Category: "A", Points: 3 }, { SupplierName: "Praveen", Category: "A", Points: 7 }],
    hash = Object.create(null),
    result = [];

dataObject.forEach(function (a) {
    var key = ['SupplierName', 'Category'].map(function (k) { return a[k]; }).join('|');
    if (a.Points === undefined || a.Points === null) {
        return;
    }
    if (!hash[key]) {
        hash[key] = { count: 0, data: { SupplierName: a.SupplierName, Category: a.Category, Points: 0 } };
        result.push(hash[key].data);
    }
    hash[key].data.Points += a.Points;
    hash[key].count++;
});

Object.keys(hash).forEach(function (k) {
    hash[k].data.Average = hash[k].data.Points / hash[k].count;
});

console.log(result);

.as-console-wrapper { max-height: 100% !important; top: 0; }




答案 3 :(得分:0)

您可以使用forEach()首先创建新数组,然后再次使用递增的对象计算平均值。



var dataObject=[ 
{ "SupplierName" : "John", "Category " : "A", "Points" : 3 },
{ "SupplierName" : "John", "Category " : "A", "Points" : 11 },
{ "SupplierName" : "John", "Category " : "A", "Points" :  0},
{ "SupplierName" : "John", "Category " : "B", "Points" : 2 },
{ "SupplierName" : "John", "Category " : "B", "Points" : 6 },
{ "SupplierName" : "Praveen", "Category " : "A", "Points" : 3 },
{ "SupplierName" : "Praveen", "Category " : "A", "Points" : 7 } 
];

var result = [], avg = {}

dataObject.forEach(function(e, i) {
  var key = e.SupplierName + '|' + e['Category ']
  if (!this[key]) {
    this[key] = {"SupplierName": e.SupplierName,"Category ": e['Category '],"Points": 0,"Average": 0}
    avg[key] = 0
    result.push(this[key])
  }
  this[key].Points += e.Points
  if(e.Points) avg[key] += 1
}, {})

result.forEach(e => e.Average = (e.Points / avg[ e.SupplierName + '|' + e['Category ']]))
console.log(JSON.stringify(result, 0, 4))




答案 4 :(得分:0)

我假设类别的键是"Category"而不是"Category "(带空格)。

var dataObject=[ 
    { "SupplierName" : "John", "Category" : "A", "Points" : 3 },
    { "SupplierName" : "John", "Category" : "A", "Points" : 11 },
    { "SupplierName" : "John", "Category" : "A", "Points" : null },
    { "SupplierName" : "John", "Category" : "B", "Points" : 2 },
    { "SupplierName" : "John", "Category" : "B", "Points" : 6 },
    { "SupplierName" : "Praveen", "Category" : "A", "Points" : 3 },
    { "SupplierName" : "Praveen", "Category" : "A", "Points" : 7 }
];

// First, accumulate the results
var result = dataObject.reduce(function(acc, item){
    // Check if we already have an element with the same SupplierName and Category
    var found = acc.find(function(e){
        return e["SupplierName"] == item["SupplierName"] && e["Category"] == item["Category"];
    });

    // If exist ...
    if(found){
        // check if item has a valid Points value
        var value = item["Points"];
        // if it has a valid value then ...
        if(value){
            // add it to points and ...
            found["Points"] += (item["Points"] || 0);
            // increment Average (Average will serve as a counter for later when we will really calculate the real average)
            found["Average"]++;
        }
    }
    // If it doesn't exists then push a new element to the accumulator with ...
    else{
        acc.push({
            "SupplierName": item["SupplierName"], // the same SupplierName and ...
            "Category": item["Category"], // the same Category and ...
            "Points": item["Points"] || 0, // a valid value for Points (0 if item doesn't have a valid one) and ...
            "Average": 1 // an accumulator for average
        });
    }

    return acc;
}, []);

// Second, calculate the real average by ...
result.forEach(function(item){
    // ... calculating the real average (what did you think was going to happen :D) 
    item["Average"] = item["Points"] / item["Average"];
});

console.log(result);