为多个键分组和添加JSON对象

时间:2015-10-19 14:54:56

标签: javascript json

我有这个JSON数据,其结构类似于

data =[{"name":"A","Date":"10/19/2015","OnTime":"0.1","Purpose":"x","OffTime":"0"},
       {"name":"A","Date":"10/19/2015","OnTime":"0.3","Purpose":"x","OffTime":"0"},
       {"name":"B","Date":"10/19/2015","OnTime":"0.01","Purpose":"y","OffTime":"0"},
       {"name":"C","Date":"10/19/2015","OnTime":"0.02","Purpose":"z","OffTime":"0"},
       {"name":"C","Date":"10/19/2015","OnTime":"0.01","Purpose":"x","OffTime":"0"}
       {"name":"A","Date":"10/20/2015","OnTime":"0.01","Purpose":"x","OffTime":"0"}]

我正在尝试对name和Date添加OnTime值。例如,2015年10月19日A的总Ontime值 预期的O / P:

dataout = [{"name":"A","Date":"10/19/2015","OnTime":"0.4"},
           {"name":"A","Date":"10/20/2015","OnTime":"0.01"},
           {"name":"B","Date":"10/19/2015","OnTime":"0.01"},
           {"name":"C","Date":"10/19/2015","OnTime":"0.03"}]

我尝试使用搜索解决方案,但找到了单键添加的解决方案,但没有找到多个键的解决方案。我也尝试使用下划线js但无法获得预期的输出。请帮助,谢谢。

3 个答案:

答案 0 :(得分:2)

好的,我有一些适合你的东西。

见小提琴:

http://jsfiddle.net/chrislewispac/nw0bberb/1

//make new sorted array for future map loop which goes in order
//using underscore.js you can chain methods. The sortBy method
//allows chaining and by multiple attributes. First sort by name
//then sort by date and return the value to new array 'sorted'

var sorted = _.chain(data)
  .sortBy(function(d) {return d.name})
  .sortBy(function(d) { return d.Date })
  .value()

//declare vars for loop
var prevObj = {};
var indexToChange = 0;
var reformattedArray = [];

//map loop over newly sorted array. I use map here which creates a new 
//array with the results of calling a provided function on every 
//element in this array.

var reformattedArray = sorted.map(function (obj, index) {

    //if the previous objects date is the same as the current objects 
    //date then take index of array which contains previous object
    //which had same name and date properties and combine the OnTime
    //values after converting them to float values using parseFloat()

    if (prevObj.Date == obj.Date && prevObj.name == obj.name) {
        reformattedArray[indexToChange].OnTime = parseFloat(prevObj.OnTime) + parseFloat(obj.OnTime);
    } 

    //if they don't match then add current object to the end of 
    //the new array

    else {
        reformattedArray.push(obj);
    }

    //at the end of the loop assign the current object to value prevObj
    //to be used in the next iteration
    prevObj = obj;

    //get current length of array (which is being built in our loop)
    //and subtract one to get index of previous object
    indexToChange = reformattedArray.length - 1;

    //return the newly reformatted array

    return reformattedArray;

});

console.log(reformattedArray[0]);

输出结果为:

[ 
   {"name":"A","Date":"10/19/2015","OnTime":0.4,"Purpose":"x","OffTime":"0"},
{"name":"B","Date":"10/19/2015","OnTime":"0.01","Purpose":"y","OffTime":"0"},
{"name":"C","Date":"10/19/2015","OnTime":0.03,"Purpose":"z","OffTime":"0"},
{"name":"A","Date":"10/20/2015","OnTime":"0.01","Purpose":"x","OffTime":"0"}
]

<强>参考文献:

Underscore: sortBy() based on multiple attributes

http://underscorejs.org/

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseFloat

答案 1 :(得分:0)

const data = [{"name":"A","Date":"10/19/2015","OnTime":"0.1","Purpose":"x","OffTime":"0"},
   {"name":"A","Date":"10/19/2015","OnTime":"0.3","Purpose":"x","OffTime":"0"},
   {"name":"B","Date":"10/19/2015","OnTime":"0.01","Purpose":"y","OffTime":"0"},
   {"name":"C","Date":"10/19/2015","OnTime":"0.02","Purpose":"z","OffTime":"0"},
   {"name":"C","Date":"10/19/2015","OnTime":"0.01","Purpose":"x","OffTime":"0"},
   {"name":"A","Date":"10/20/2015","OnTime":"0.01","Purpose":"x","OffTime":"0"}];

var resultArr = [];
for (let fetchData of data) {
  var indx = data.indexOf(fetchData);
  for (var i = indx + 1; i < data.length; i++) {
    if (fetchData.name == data[i].name && fetchData.Date == data[i].Date) {
      let onTimeSum = parseFloat(fetchData.OnTime) +
        parseFloat(data[i].OnTime);
      fetchData.OnTime = JSON.stringify(onTimeSum);
      resultArr.push(fetchData);
    }
  }
  //Find Objects which is already pushed having same name and date as current object
  var findDuplicates = resultArr.filter(function(data) {
    if (data.name == fetchData.name && data.Date == fetchData.Date) {
      return data;
    }
  });
  //We will not push same object having same name and date again
  if (findDuplicates.length == 0) {
    resultArr.push(fetchData);
  }
}
console.log('resultArr' + JSON.stringify(resultArr));

答案 2 :(得分:-3)

这样的事情可能是:

function GroupBy(array){
  var fields = Array.prototype.slice.call(arguments, 1);
  var field = fields.shift();

  if(field){

    var groupedArray = [];
    for(var i in array){
      var index = array[i][field];
      groupedArray[index] = groupedArray[index] || [];
      groupedArray[index].push(array[i]);
    }

    for(var i in groupedArray)
      groupedArray[i] = GroupBy.bind(null, groupedArray[i]).apply(null, fields);

    return groupedArray;
  }

  return array;
}

没有测试过,所以不要期望它能够正常工作。但这应该是一个好的开始。

这就是你使用它的方式。

var array = [...]; //your array
var groupedArray = GroupBy(array, "name", "Date");

//Then to get records by a specific fields just:
var A_10192015 = groupedArray["A"]["10/19/2015"];