Sort and merge JSON keys with matching values

2019-03-02 05:50发布

问题:

My JSON looks like this:

json = [
  {
    type: "big"
    date: "2012-12-08"
    qty: 6
  }
  {
    type: "small"
    date: "2012-12-08"
    qty: 9
  }
  {
    type: "big"
    date: "2012-12-15"
    qty: 4
  }
  {
    type: "small"
    date: "2012-12-07"
    qty: 7
  }
  {
    type: "small"
    date: "2012-11-07"
    qty: 3
  }
]    

What I'm trying to do is group/merge each type that has a date with the same year & month (the first 7 characters in the date string) and get the sum of those qty's. The output should look like this:

json = [
  {
    type: "big"
    date: "2012-12"
    qty: 10
  }
  {
    type: "small"
    date: "2012-12"
    qty: 16
  }
  {
    type: "small"
    date: "2012-11"
    qty: 3
  }
]  

There are several similar questions I've found here but haven't come across one that does exactly what I'm looking for. I have played around with lots of code borrowed from different examples but can't quite seem to get the results I need. I'm not home now, therefore I can't paste any code I've tried at the moment but I'm asking for help in hopes to have an answer/solution to test out later

回答1:

This is easily handled by creating a custom object that has properties named with your unique combinations (i.e. type + first 7 of date).

Loop through your array and check if your "holder" object has an existing property named with your unique identifier. If it has the property already, then increment the quantity, otherwise add a new item.

After the holder is completely built, clear your array, then loop through the properties of the holder and push them back on to your array.

var holder = {};
var json = [
  {
    type: "big",
    date: "2012-12-08",
    qty: 6
  },
  {
    type: "small",
    date: "2012-12-08",
    qty: 9
  },
  {
    type: "big",
    date: "2012-12-15",
    qty: 4
  },
  {
    type: "small",
    date: "2012-12-07",
    qty: 7
  },
  {
    type: "small",
    date: "2012-11-07",
    qty: 3
  }
];

json.forEach(function(element) {
  var identifier = element.type + element.date.slice(0, 7);
  if (holder[identifier]) {
    holder[identifier].qty += element.qty;
  } else {
    holder[identifier] = element;
  };
});

json = [];
for(var identifier in holder) {
  json.push(holder[identifier]);
}

console.log(json);



回答2:

Alternative solution:

var result = [];

$(json).each(function (i, e){
    var search = $.grep(result, function(elm){ return e.type == elm.type && e.date.substring(0, 7) == elm.date; });
    if(search.length == 0)
        result.push({ type: e.type, date: e.date.substring(0, 7), qty: e.qty });
    else
        search[0].qty += e.qty;
});


回答3:

One more to mix which I think this is the longest answer of them all :-)

    var sortedArray = [];

    function traverseArray(element, index, array) {
        
        var found = false;
        
        for (i = 0; i < sortedArray.length; i++) {
            if (sortedArray[i].type === element.type) {
                if (sortedArray[i].date.substring(0, 7) === element.date.substring(0, 7)) {
                    sortedArray[i].qty = (sortedArray[i].qty + element.qty);
                    console.log(element);
                    found = true;
                }
            }
        }
        
        if (!found)
            sortedArray.push(element);
    }
    
    
    
    var data = [{
        type: "big",
        date: "2012-12-08",
        qty: 6
    }, {
        type: "small",
        date: "2012-12-08",
        qty: 9
    }, {
        type: "big",
        date: "2012-12-15",
        qty: 4
    }, {
        type: "small",
        date: "2012-12-07",
        qty: 7
    }, {
        type: "small",
        date: "2012-11-07",
        qty: 3
    }];
    
    data.forEach(traverseArray);
    
    sortedArray.forEach(print);
    
    function print(element, index, array) {
        var line = "[ type: " + element.type + ", date: " + element.date + ", qty: " + element.qty + "]";
      $("#result").append(line  +  " <br>");
    }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="result"></div>