2013-07-25 7 views
5

Я использую JavaScript. У меня есть массив, содержащий данные в этом формате:Как я могу группировать массив объектов по месяцам?

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

(цифры выше, представляют собой дату UTC/время в миллисекундах

Я хотел бы группа (количество) данные по месяцам Что-то вроде этого.. :

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

я мог бы использовать jQuery, если это упрощает дело

+2

Этот объект возвращается с сервера? Если это так, я бы рекомендовал вернуть данные в правильном формате клиенту, а не добавлять логику разбора в java-скрипт. Как правило, это проще и надёжнее для тестирования этого типа логики на сервере. – TGH

+0

Да, я получаю данные с сервера в [oData] (http://www.odata.org/). Это означает, что мне, возможно, даже не придется менять код сервера, а скорее использовать опцию «$ count» oData (я не уверен, что это даст мне то, что я хочу). Тем не менее, у меня уже есть необработанные данные в клиенте из предыдущего запроса, и я хотел бы сохранить туда и обратно. – Perspectivus

+0

Пожалуйста, отметьте этот вопрос как ответ, если мой ответ ниже действительно удовлетворительный. В противном случае, уточните. – pygeek

ответ

10

Это выглядит как mapreduce проблемы. Решение высокого уровня выглядит следующим образом:

  1. Восстановите список участников.
  2. Подсчитайте их.

Вот шаг за шагом, как к для достижения этой цели:

Карты

  1. Итерации по списку словарей
  2. Преобразовать DATETIME строки объектов JavaScript даты и время ,
  3. Используйте месяц-год как ключ и список словарей в качестве значения.

В настоящее время они сгруппированы по месяцам.

Пример:

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 

Уменьшить

  1. итерацию через новый объект, содержащий словари списков.
  2. Рассчитать длину каждого словаря.
  3. Использовать count как ключ и длину списка как его значение.

Пример:

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 
} 

Результирующее 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. 

Литература:

Для map и reduce фу nctions в JavaScript см underscore.js:
http://underscorejs.org/#map
http://underscorejs.org/#reduce

Javascript Дата объекта:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date

Для получения дополнительной информации о дате и DateTime объекты:
https://en.wikipedia.org/wiki/ISO_8601

Для получения дополнительной информации о mapreduce:
https://en.wikipedia.org/wiki/MapReduce

+0

Спасибо @pygeek за ваш сложный ответ. Я не могу использовать источники с открытым исходным кодом или сторонние источники, отличные от jQuery, поэтому underscorejs для меня. Я буду использовать карту jQuery и массив массивов JavaScript. – Perspectivus

1

Использование Map-reduce. Вот один пример использования underscore.js. Это очень просто, хотя это немного многословно.

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); 
Смежные вопросы