2016-02-16 2 views
1

У меня есть массив данных, как следующие, отсортированных по месяцам по возрастанию:Underscore.js: Фильтровать массив объектов, а затем сортировать в среднем?

[{ 
    org_id: "K83002", 
    percentile: 1, 
    date: "2013-11-01", 
}, 
{ 
    org_id: "K83059", 
    percentile: 33, 
    date: "2013-12-01", 
}, 
{ 
    org_id: "K83607", 
    percentile: 22, 
    date: "2013-12-01", 
} ... 

Я хочу, чтобы создать упорядоченный список организаций, ранжированный по их средней процентиль позиции в течение последних трех месяцев в данных.

Прямо сейчас, я это делаю:

  var lastThreeMonths = _.uniq(_.pluck(data, 'date'), true).slice(-3); 
      var averages = {}; 
      var lastMonths = _.each(data, function(d) { 
       if (_.contains(lastThreeMonths, d.date)) { 
        if (d.org_id in averages) { 
         averages[d.org_id] += d.percentile; 
        } else { 
         averages[d.org_id] = d.percentile; 
        } 
       } 
      }); 
      var temp = []; 
      for (var k in averages) { 
       temp.push({ 'org_id': k, 'percentile': averages[k]}); 
      } 
      var sortedAvgs = _.sortBy(temp, 'percentile').reverse(); 

Но это очень многословны. Есть ли лучший способ сделать это?

В идеале я также хотел бы приложить необработанные данные для каждой организации отсортированным массивом, так как я буду перебирать отсортированный массив рядом, и было бы удобно получить доступ к данным внутри этого итератора.

+0

Вы можете показать немного больше входного и что выход он должен генерировать? – Amit

ответ

0

Вы можете попробовать это:

var sortedAverages = _.chain(data) 
    .filter(d => _.contains(lastThreeMonths, d.date)) 
    .groupBy('org_id') 
    .map(eachOrg => { 
    var average = _.sum(_.pluck(eachOrg, 'percentile')); 
    return { 
     org_id : eachOrg.org_id, 
     percentile : average 
    }; 
    }) 
    .sortBy('percentile') 
    .value() 
    .reverse(); 
+0

Спасибо! Это красиво и компактно, но я не уверен, как переписать его для совместимости с предварительным ES6. Кроме того, откуда происходит 'eachOrg'? – Richard

+0

eachOrg - фактически аргумент функции. Прочитайте функции стрелок ES6. Если вы сделаете это в es5, это будет выглядеть так: '' 'function (eachOrg) {/ * ... * /}' '' –

0

Это должно помочь вам:

// Create a hash of allowed dates - much improved performance over arrays for larger data sets 
var lastThreeMonthsHash = _.chain(data).pluck('date').uniq().slice(-3).map(function (date) { 
    return [date, true] 
}).object().value(); 

// filter out older entries 
var grouped = _.chain(data).filter(function (monthly) { 
    return lastThreeMonthsHash[monthly.date]; 
    // group by org_id 
}).groupBy('org_id').map(function (values, orgId) { 
    // reduce each group into a single value which is the average percentile 
    var percentiles = _.pluck(values, 'percentile'); 
    var sum   = _.reduce(percentiles, function (memo, value) { 
     return memo + value; 
    }, 0); 
    return { 
     org_id : orgId, 
     percentile: sum/values.length 
    }; 
    // sort by percentile & reverse 
}).sortBy('percentile').reverse().value(); 
Смежные вопросы