2013-07-25 23 views
5

Używam JavaScript. Mam tablicę, która zawiera dane w tym formacie:Jak mogę pogrupować tablicę obiektów według miesiąca?

[ 
     {"USER_NAME":"User1","LAST_SUCCESSFUL_CONNECT":"1373978337642"}, 
     {"USER_NAME":"User2","LAST_SUCCESSFUL_CONNECT":"1374515704026"}, 
     {"USER_NAME":"User3","LAST_SUCCESSFUL_CONNECT":"1374749782479"} 
] 

(numery powyżej reprezentacji daty/czasu UTC w milisekundach

Chciałbym grupa (liczyć) dane przez miesiąc coś takiego.. :

[ 
    {"Month":"January, 2014","User_Count": 2}, 
    {"Month":"February, 2014","User_Count": 1}, 
] 

mogę użyć jQuery jeśli upraszcza sprawy

+2

Czy ten obiekt jest zwracany z serwera? Jeśli tak, zaleciłbym przekazanie danych w poprawnym formacie do klienta, zamiast dodawać logikę do parsowania w skrypcie java. Zazwyczaj jest to łatwiejsze i bardziej możliwe do testowania jednostkowego, aby uruchomić ten typ logiki na serwerze. – TGH

+0

Tak, otrzymuję dane z serwera w [oData] (http://www.odata.org/). Oznacza to, że nie muszę nawet zmieniać kodu serwera, ale raczej użyć opcji '$ count' oData (nie jestem pewien, czy dałoby mi to, czego chcę). Jednak mam już surowe dane w kliencie z poprzedniego zapytania i chciałbym zapisać w obie strony. – Perspectivus

+0

Proszę zaznaczyć to pytanie jako odpowiedź, jeśli moja odpowiedź poniżej jest rzeczywiście satysfakcjonująca. W przeciwnym razie opracuj. – pygeek

Odpowiedz

10

To wygląda jak mapreduce problemu. Rozwiązanie wysokiego poziomu jest następujące:

  1. Ponownie uporządkuj członków listy.
  2. Policz je.

Oto krok po kroku jak to zrobić dla osiągnięcia tego celu:

Mapa

  1. iterację listy słowników
  2. Convert datetime ciąg JavaScript Object datetime .
  3. Używaj miesiąca-roku jako klucza i listy słowników jako wartości.

Są one teraz pogrupowane według miesięcy-roku.

przykład:

var l = [...]; 
var o = {}; 
var f = function(x){ 
    var dt_object = Date(x["LAST_SUCCESSFUL_CONNECT"]); // convert to datetime object 
    var key = dt_object.year + '-' + dt_object.month; 

    if (o[key] === undefined) { 
     var o[key] = []; 
    }; 

    o[key].push(x) 
} 

_.map(l, f(x)) //apply f to each member of l 

Zmniejszenie

  1. iterację nowego obiektu zawierającego słowniki list.
  2. Oblicz długość każdej listy słownika.
  3. Użyj count jako klucza i długości listy jako jej wartości.

przykład:

var g = function(member_count){ 
    //extra logic may go here 
    return member_count 
} 

for member in o { 
    count = _.reduce(l, g(member)) 
    member['count'] = count 
} 

Wynikające API

o['month-year'] //for list of dictionaries in that month 
o['month-year']['count'] //for the count of list of dictionaries in that month. 

Odniesienia:

Na map i reduce fu nctions w javascript zobaczyć underscore.js:
http://underscorejs.org/#map
http://underscorejs.org/#reduce

Javascript obiekt Date:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date

Więcej informacji na temat daty i DateTime obiektów:
https://en.wikipedia.org/wiki/ISO_8601

Więcej informacji na temat mapreduce:
https://en.wikipedia.org/wiki/MapReduce

+0

Dzięki @pygeek za wyczerpującą odpowiedź. Nie mogę używać źródeł otwartego źródła lub źródeł zewnętrznych innych niż jQuery, więc program underscorejs jest dla mnie niedostępny. Wykorzystam mapę jQuery oraz redukcję tablicy JavaScript. – Perspectivus

1

Użyj opcji Map-reduce. Oto jeden przykład użycia pliku underscore.js. Jest to bardzo proste, choć jest trochę gadatliwe.

var data = [{ 
    "USER_NAME": "User1", 
     "LAST_SUCCESSFUL_CONNECT": "1373978337642" 
}, { 
    "USER_NAME": "User2", 
     "LAST_SUCCESSFUL_CONNECT": "1374515704026" 
}, { 
    "USER_NAME": "User3", 
     "LAST_SUCCESSFUL_CONNECT": "1374749782479" 
}, { 
    "USER_NAME": "User4", 
     "LAST_SUCCESSFUL_CONNECT": "1274749702479" 
}]; 

var monthNames = ["January", "February", "March", "April", "May", "June", 
    "July", "August", "September", "October", "November", "December"]; 

var map_result = _.map(data, function (item) { 
    var d = new Date(new Number(item.LAST_SUCCESSFUL_CONNECT)); 
    var month = monthNames[d.getMonth()] + ", " + d.getFullYear(); 
    return { 
     "Month": month, 
     "User_Count": 1 
    }; 
}); 

var result_temp = _.reduce(map_result, function (memo, item) { 
    if (memo[item.Month] === undefined) { 
     memo[item.Month] = item.User_Count; 
    }else{ 
     memo[item.Month] += item.User_Count; 
    } 
    return memo; 
},{}); 

//then wrap the result to the format you expected. 
var result = _.map(result_temp, function(value, key){ 
    return { 
     "Month": key, 
     "User_Count": value 
    }; 
}); 

console.log(result); 
Powiązane problemy