如何通过多个属性对javascript对象数组进行分组?

时间:2016-01-24 16:08:44

标签: javascript arrays json grouping

我想将showtimesData转换为showtimesByLocationByDate

任何想法如何不使用任何第三方库,只使用纯JavaScript?否则,我可以使用哪个第三方库?

    var showtimesData = [
        {"location":"location1", "date":"31-12-2016", "time":"1:00"},
        {"location":"location1", "date":"31-12-2016", "time":"2:00"},
        {"location":"location1", "date":"01-01-2017", "time":"3:00"},
        {"location":"location1", "date":"01-01-2017", "time":"4:00"},
        {"location":"location2", "date":"31-12-2016", "time":"1:00"},
        {"location":"location2", "date":"31-12-2016", "time":"2:00"},
        {"location":"location2", "date":"01-01-2017", "time":"3:00"},
        {"location":"location2", "date":"01-01-2017", "time":"4:00"},
    ];
    var showtimesByLocationByDate = [
        {
            "location":"location1",
            "dates":[
                {
                    "date":"31-12-2016",
                    "times":["1:00","2:00"]
                },
                {
                    "date":"01-01-2017",
                    "times":["3:00","4:00"]
                }
            ]
        },
        {
            "location":"location2",
            "dates":[
                {
                    "date":"31-12-2016",
                    "times":["1:00","2:00"]
                },
                {
                    "date":"01-01-2017",
                    "times":["3:00","4:00"]
                }
            ]
        },
    ];

2 个答案:

答案 0 :(得分:4)

此提案仅包含Array.prototype.reduce(),其中包含一个用于引用数组项的临时对象。



var showtimesData = [{ "location": "location1", "date": "31-12-2016", "time": "1:00" }, { "location": "location1", "date": "31-12-2016", "time": "2:00" }, { "location": "location1", "date": "01-01-2017", "time": "3:00" }, { "location": "location1", "date": "01-01-2017", "time": "4:00" }, { "location": "location2", "date": "31-12-2016", "time": "1:00" }, { "location": "location2", "date": "31-12-2016", "time": "2:00" }, { "location": "location2", "date": "01-01-2017", "time": "3:00" }, { "location": "location2", "date": "01-01-2017", "time": "4:00" }, ],
    showtimesByLocationByDate = showtimesData.reduce(function (r, a) {
        var o;
        if (!(a.location in r.obj)) {
            o = { location: a.location, dates: [] };
            r.obj[a.location] = { dates: o.dates };
            r.array.push(o);
        }
        if (!(a.date in r.obj[a.location])) {
            o = { date: a.date, times: [] };
            r.obj[a.location].dates.push(o);
            r.obj[a.location][a.date] = o.times;
        }
        r.obj[a.location][a.date].push(a.time);
        return r;
    }, { array: [], obj: {} }).array;

document.write('<pre>' + JSON.stringify(showtimesByLocationByDate, 0, 4) + '</pre>');
&#13;
&#13;
&#13;

奖励:具有给定数据结构的通用版本

&#13;
&#13;
var showtimesData = [{ "location": "location1", "date": "31-12-2016", "time": "1:00" }, { "location": "location1", "date": "31-12-2016", "time": "2:00" }, { "location": "location1", "date": "01-01-2017", "time": "3:00" }, { "location": "location1", "date": "01-01-2017", "time": "4:00" }, { "location": "location2", "date": "31-12-2016", "time": "1:00" }, { "location": "location2", "date": "31-12-2016", "time": "2:00" }, { "location": "location2", "date": "01-01-2017", "time": "3:00" }, { "location": "location2", "date": "01-01-2017", "time": "4:00" }, ],
    structure = [
        { key: 'location', data: 'dates' },
        { key: 'date', data: 'times' },
        { key: 'time' }
    ],
    showtimesByLocationByDate = showtimesData.reduce(function (r, a) {
        var properties = structure.slice(),
            lastKey = properties.pop().key;

        properties.reduce(function (rr, b) {
            var o = {},
                p = {},
                key = b.key,
                value = a[key],
                array = b.data;

            if (!(value in rr.obj)) {
                o[key] = value;
                o[array] = [];
                p[array] = o[array];
                rr.obj[value] = p;
                rr.array.push(o);
            }
            return { array: rr.obj[value][array], obj: rr.obj[value] };
        }, r).array.push(a[lastKey]);

        return r;
    }, { array: [], obj: {} }).array;

document.write('<pre>' + JSON.stringify(showtimesByLocationByDate, 0, 4) + '</pre>');
&#13;
&#13;
&#13;

答案 1 :(得分:4)

我建议进行这种转变:

&#13;
&#13;
var showtimesData = [
        {"location":"location1", "date":"31-12-2016", "time":"1:00"},
        {"location":"location1", "date":"31-12-2016", "time":"2:00"},
        {"location":"location1", "date":"01-01-2017", "time":"3:00"},
        {"location":"location1", "date":"01-01-2017", "time":"4:00"},
        {"location":"location2", "date":"31-12-2016", "time":"1:00"},
        {"location":"location2", "date":"31-12-2016", "time":"2:00"},
        {"location":"location2", "date":"01-01-2017", "time":"3:00"},
        {"location":"location2", "date":"01-01-2017", "time":"4:00"},
    ];
  
var transformed = showtimesData.reduce(function(obj, show){
  //var { location, date, time } = show; //if destructuring is available
  var location = show.location,
      date = show.date,
      time = show.time,
      objLocation = obj[location] = obj[location] || { dates : { } },
      dates = objLocation.dates,
      date = dates[date] = dates[date] || [ ];

      date.push(time);
      return obj;
}, {});
results.innerHTML = JSON.stringify(transformed, null, '\t');
&#13;
<pre id="results"></pre>
&#13;
&#13;
&#13;

但是如果你真的想把它改造成那样的话,我建议把它转换成你建议的结构。

&#13;
&#13;
var showtimesData = [
        {"location":"location1", "date":"31-12-2016", "time":"1:00"},
        {"location":"location1", "date":"31-12-2016", "time":"2:00"},
        {"location":"location1", "date":"01-01-2017", "time":"3:00"},
        {"location":"location1", "date":"01-01-2017", "time":"4:00"},
        {"location":"location2", "date":"31-12-2016", "time":"1:00"},
        {"location":"location2", "date":"31-12-2016", "time":"2:00"},
        {"location":"location2", "date":"01-01-2017", "time":"3:00"},
        {"location":"location2", "date":"01-01-2017", "time":"4:00"},
    ];
  
var transformed = showtimesData.reduce(function(obj, show){
  //var { location, date, time } = show; //if destructuring is available
  var location = show.location,
      date = show.date,
      time = show.time,
      objLocation = obj[location] = obj[location] || { dates : { } },
      dates = objLocation.dates,
      date = dates[date] = dates[date] || [ ];

      date.push(time);
      return obj;
}, {});

var secondTransformed = Object.keys(transformed).map(function(key){
  var dates = transformed[key].dates,
      transformedDates = Object.keys(dates).map(function(key){
          return { date : key, times : dates[key] }
      });
  return { location : key, dates : transformedDates }
});
results.innerHTML = JSON.stringify(secondTransformed, null, '\t');
&#13;
<pre id="results"></pre>
&#13;
&#13;
&#13;

虽然有更好的方法可以做到这一点(性能明智)。