2016-01-24 8 views
6

Voglio convertire showtimesData in showtimesByLocationByDate

Qualche idea su come farlo senza utilizzare alcuna libreria di terze parti e utilizzando solo JavaScript puro? Altrimenti, quale libreria di terze parti posso usare per questo?Come raggruppare un array di oggetti javascript per più delle sue proprietà?

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"] 
       } 
      ] 
     }, 
    ]; 
+0

Deve seguire quel formato specifico? La ricerca della data sarebbe molto più veloce se fosse una proprietà di un oggetto. – MinusFour

+0

se dovessi impostare le date come proprietà, posso scorrere le proprietà per ottenere le date come stringhe? – davidchoo12

+0

Sì, è possibile scorrere le proprietà dell'oggetto. – MinusFour

risposta

4

Questa proposta presenta solo Array.prototype.reduce() con un oggetto temporaneo per fare riferimento gli elementi di matrice.

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>');

Bonus: versione generico con una data struttura di dati

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>');

+0

La tua risposta è molto precisa, ma mi stavo chiedendo se c'è un modo per renderlo più generico? – Rajesh

+0

@Rajesh, dipende dalla struttura dei dati e dalla sua genericità. –

+0

Mi stavo chiedendo se potremmo creare una funzione in cui passiamo dati e proprietà per raggruppare, e restituisce un valore raggruppato. Di seguito è riportato [JSFiddle] (https://jsfiddle.net/RajeshDixit/sktkjpno/) che ho già provato. – Rajesh

4

avrei propongo questa trasformazione:

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');
<pre id="results"></pre>

Ma se si vuole veramente per trasformarla a questo, mi piacerebbe propongo grabing questa trasformazione e la mappa per la vostra struttura proposta.

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');
<pre id="results"></pre>

Anche se ci sono modi migliori per fare questo (performance saggio).

+1

Registri 'Uncaught SintassiErrore: Token imprevisto {' a 'console' – guest271314

+0

È l'assegnazione destrutturante, il tuo browser non lo supporta ancora. – MinusFour

+0

Ok, proverò al browser diverso – guest271314

Problemi correlati