获取JavaScript对象中具有匹配键的所有值的总和?

时间:2014-10-14 19:58:07

标签: javascript json

我正在尝试创建一个基于密钥对值进行求和的函数。这是一个示例对象:

{
  "US": {
    "q": 1,
    "Atlanta": {
      "q": 2
    },
    "Boston": {
      "q": 1
    }
}

我希望能够调用类似的函数:

var sum = plucky("q", obj);
// sum === 4;

我正在使用的功能,我相信我从过去某处的某个帖子中找到的几乎是正确的:

function pluckDeepKey(key, obj) {
  if (_.has(obj, key)) {
    return obj[key];
  }
  return _.reduce(_.flatten(_.map(obj, function(v) {
    return _.isObject(v) ? pluckDeepKey(key, v) : [];
  }), false), function(a,b) { return a + b });
}

但是,由于:return obj[key]它找到第一个"q",返回该值并退出。我整天都在摸不着头脑,如果我把这个问题扔到SO那就认为对别人有帮助。

修改

我认为SO和我未来的自我收集我在问题主体中探索的不同方法可能是有用的。

Vanilla JavaScript(来自dfsq)

function plucky(key, obj) {
    var sum = 0;
    for (var prop in obj) {
        if (_.has(obj, prop) && key === prop) {
            sum += obj[prop];
        }
        else if (_.isObject(obj[prop])) {
            sum += plucky(key, obj[prop]);
        }
    }
    return sum;
}

Lodash(下划线?)功能实例(通过Bergi)

function pluckDeepKey(key, obj) {
  return _.reduce(obj, function(a, v) {
    return a + (_.isObject(v) ? pluckDeepKey(key, v) : 0);
  }, _.has(obj, key) ? obj[key] : 0);
}

Mori.js& Immutable.js功能实例

function moriDeepKey(key, mmap) {
  return m.reduce_kv(
    function(a, k, v) { return a + (m.is_map(v) ? moriDeepKey(key, v) : 0); },
    m.has_key(mmap, key) ? mmap.get(key) : 0,
    mmap
  );
}
function iDeepKey(key, imap) {
  return imap.reduce(
    function(a, v, k) { return a + (v instanceof I.Map ? iDeepKey(key, v) : 0); },
    imap.has(key) ? imap.get(key) : 0,
    imap
  );
}

4 个答案:

答案 0 :(得分:2)

我认为普通的javascript函数看起来更全面,更简单:

function plucky(key, obj) {

    var sum = 0;

    for (var prop in obj) {
        if (obj.hasOwnProperty(prop) && key === prop) {
            sum += obj[prop];
        }
        else if (Object.prototype.toString.call(obj[prop]) === '[object Object]') {
            sum += plucky(key, obj[prop]);
        }
    }

    return sum;
}

function plucky(key, obj) {

    var sum = 0;

    for (var prop in obj) {
        if (obj.hasOwnProperty(prop) && key === prop) {
            sum += obj[prop];
        } 
        else if (Object.prototype.toString.call(obj[prop]) === '[object Object]') {
            sum += plucky(key, obj[prop]);
        }
    }

    return sum;
}


var obj = {
    "US": {
        "q": 1,
        "Atlanta": {"q": 2},
        "Boston": {"q": 1}
    }
};
var sum = plucky("q", obj);
alert(sum);

答案 1 :(得分:2)

  

但是,由于:return obj[key]它找到第一个"q",返回该值并退出。

通过使用值作为累加器的开头,将两部分(obj.q和递归调用)相加:

function pluckDeepKey(key, obj) {
  return _.reduce(_.map(obj, function(v) {
    return _.isObject(v) ? pluckDeepKey(key, v) : 0;
  }), function(a,b) {
    return a + b;
  }, _.has(obj, key) ? obj[key] : 0);
}

我也删除了不必要的flatten调用(pluckDeepKey总是返回一个数字,空的arrray应该只是0)。如果需要,您还可以将reducemap加入

function pluckDeepKey(key, obj) {
  return _.reduce(obj, function(a, v) {
    return a + (_.isObject(v) ? pluckDeepKey(key, v) : 0);
  }, _.has(obj, key) ? obj[key] : 0);
}

答案 2 :(得分:1)

除了另一个答案之外,您可以使用内置的所有内容以及使用递归功能实现更多功能:

var plucky = function(key, obj) {
  return Object.keys(obj).reduce(function(acc, k) {
    if ({}.toString.call(obj[k]) == '[object Object]') {
      return acc + plucky(key, obj[k])
    }
    if (k === key) {
      return acc + obj[k]
    }
    return acc
  },0)
}

答案 3 :(得分:0)

您可以使用以下内容:

function plucky(key, obj) {
    var sum = 0;
    if(typeof obj == "object") {
        for(var val in obj) {
            if(typeof obj[val] == "object") {
                sum += plucky(key, obj[val]);
            } else if(val == key) {
                sum += obj[val];
            }
        }
    } else if(val == key) {
        sum += obj[val];
    }
    return sum;
}
相关问题