如何使用哈希图或数组映射返回总数最高的类别

How can I use a hashmap or map of an array to return the category with the highest total?

本文关键字:返回 哈希图 何使用 数组 映射      更新时间:2023-09-26

这是我的数组。

donations = [
 {
      donateTo: "BaseCamp",
      amount: 1000,
      date: "12/19/2014, 08:40"
 },
 {
      donateTo: "Where Most Needed",
      amount: 3000,
      date: "12/12/2014, 08:40"
 },
 {
      donateTo: "Where Most Needed",
      amount: 2000,
      date: "12/11/2014, 08:40"
 }
 ];

我怎样才能退回这样的东西?捐赠总额最高的donateTo的捐款与该捐款总额和构成该总额的礼物计数一起退还。

{ donateTo: "Where Most Needed", total: 5000, count: 2}

我以前能够用MongoDB得到结果,但是因为我使用的是Meteor,所以聚合真的很丑陋,没有反应性。我宁愿获取光标,然后在客户端使用javascript函数来获取我需要的数据。

谢谢

下面是使用下划线的实现:

var orgs = {};
_.each(donations, function(donation) {
  if (orgs[donation.donateTo] == null)
    orgs[donation.donateTo] = 0;
  orgs[donation.donateTo] += donation.amount;
});
var amount = _.max(_.values(orgs));
var donateTo = _.invert(orgs)[amount];
var count = _.where(donations, {donateTo: donateTo}).length;
var result = {donateTo: donateTo, amount: amount, count: count};
console.log(result);

您可以循环遍历项目并将它们分组到一个对象中,然后循环访问对象中的属性以查找最大数量:

var donations = [
  {
      donateTo: "BaseCamp",
      amount: 1000,
      date: "12/19/2014, 08:40"
  },
  {
      donateTo: "Where Most Needed",
      amount: 3000,
      date: "12/12/2014, 08:40"
  },
  {
      donateTo: "Where Most Needed",
      amount: 2000,
      date: "12/11/2014, 08:40"
  }
];
var sums = {};
for (var i = 0; i < donations.length; i++) {
  var donateTo = donations[i].donateTo;
  if (sums.hasOwnProperty(donateTo)) {
    sums[donateTo].amount += donations[i].amount;
    sums[donateTo].count++;
  } else {
    sums[donateTo] = { donateTo: donateTo, amount: donations[i].amount, count: 1 };
  }
}
var obj = null;
for (donateTo in sums) {
  if (obj == null || sums[donateTo].amount > obj.amount) {
    obj = sums[donateTo];
  }
}
// show in Stackoverflow snippet
document.write(JSON.stringify(obj));

您可以先循环访问文档,以按donateTo字段将它们组合在一起。

var m = {}; // to hold the grouped records by `donateTo`
 donations.forEach(function(i){
    if(!m[i["donateTo"]]){
        m[i["donateTo"]] = {};
        m[i["donateTo"]] = i;
        m[i["donateTo"]]["count"] = 1;
    }
    else{
        m[i["donateTo"]]["count"]++;
        m[i["donateTo"]]["amount"] += i.amount;
    }
 });

然后找到数量最多的组:

 var result = {amount:0}; // to hold the group with the largest amount
 Object.keys(m).forEach(function(key){
    if(m[key].amount > result.amount){
        result = m[key];
    }
 })
delete result["date"];
console.log(result);

没有超级巧妙的方法可以做到这一点,因为您必须累积所有总计,然后在最后选择最高的一个,数组中的最后一个条目可能会完全更改最大值,因此您必须累积所有小计。

下面的此函数累积遇到的所有donateTo字符串的映射,并为每个字符串保留运行总计和 cnt。 随着它的进行,它会跟踪到目前为止哪个键的总数最高donateTo从而节省了额外的传递来计算最高的通道。

function findHighestSum(list) {
    // collect cumulative totals
    var totals = {}, highestTotal = 0, highestKey;
    list.forEach(function(item) {
        var key = item.donateTo;
        if (!totals[key]) {
            totals[key] = {amount: item.amount, cnt: 1};
        } else {
            totals[key].amount += item.amount;
            totals[key].cnt++;
        }
        if (totals[key].amount > highestTotal) {
            highestTotal = totals[key].amount;
            highestKey = key;
        }
    });

    // { donateTo: "Where Most Needed", total: 5000, count: 2}
    return {donateTo: highestKey, total: highestTotal, count: totals[highestKey].cnt};
}

工作演示:http://jsfiddle.net/jfriend00/7cfdsftz/

因为下划线很有趣!

_.chain(donations)
  .reduce(function(m, c) {
      var findItem = _.findWhere(m, { 'donateTo': c.donateTo});
      if (findItem) {
          findItem.count++; 
          findItem.total += c.amount;
      } else {
          m.push({
             'donateTo':c.donateTo, 
             'count':1, 
             'total':c.amount});
      };
      return m; }, [])
  .max(function(k) { return k.total})
  .value();

使用下划线...

// reduce donations, finally returning object with largest amount total
var highest = _.reduce(donations, function(memo, item, index){
    // add to amount total if group exists, else init group
    if(memo[item.donateTo]){
        memo[item.donateTo].amount += item.amount;
        memo[item.donateTo].count++;
    } else {
        memo[item.donateTo] = {
            donateTo: item.donateTo,
            amount:item.amount,
            count:1
        };
    }
    // if it is last iteration...
    if(index === donations.length - 1){
        // extract the max value
        memo = _.max(_.toArray(memo), function(item){
            return item.amount;
        });
    }
    return memo;
}, {});

使用下划线 js ...

// return the max (amount) of sorted, and collapsed array
var result = _.max( _.reduce( _.sortBy(donations, 'donateTo'), function(memo, item){
    // if the last item has same key, update it (items are sorted by `donateTo`)
    var _last = _.last(memo);
    if(_last && _last.donateTo === item.donateTo){
        _last.amount += item.amount;
        _last.count++;
    // otherwise create it
    } else {
        memo.push( _.extend( _.omit(item, 'date'), {'count':1} ) );
    }
    return memo
}, []), 'amount');

下划线高尔夫...

var h = {}, c={};
var result = _.max(donations, function(o){ var i = o.donateTo;
    delete o.date; c[i] = ++c[i]||1; o.count=c[i];
    return o.amount = h[i] = (h[i]||0)+o.amount
});