【问题标题】:Getting name from nesting arrays from matching arrays从匹配数组中的嵌套数组中获取名称
【发布时间】:2017-12-18 16:06:38
【问题描述】:

我有一些数组,如果它们包含相似的值,我想返回这些数组的名称。

变量 x = { “食物”:['培根','奶酪','面包','番茄'], "utilities": ['plates', 'forks', 'spatulas'], “客人”:['约翰','马特','比尔'] }, y = ['培根','番茄','叉子'];

我有我的变量x,它有多个数组,名称为foodutilitiesguestsy 包含的所有内容,是在 x 的变量中的一些数组中相同的一些值。我需要返回数组中包含bacontomatoforks 的数组的名称。所以对于这个例子,我需要返回:["food", "utilities"]

函数getContainerName(obj,值){ 返回 Object.keys(obj).find(function(key) { return values.every(value => obj[key].find(function(elem) { 返回元素 === 值; })); }); } console.log(getContainerName(x, y));

当通过这个函数抛出它们时,我得到一个错误*********。我怎样才能得到一个返回的["food", "utilities"]数组?

【问题讨论】:

    标签: javascript arrays loops object properties


    【解决方案1】:

    Object.keys 上的一个简单的reduce() 就可以完成这项工作

    var x = {
        "food": ['bacon', 'cheese', 'bread', 'tomato'],
        "utilities": ['plates', 'forks', 'spatulas'],
        "guests": ['john', 'matt', 'bill']
      },
      y = ['bacon', 'tomato', 'forks'];
    
    let res = Object.keys(x).reduce((a, b) => {
      if (x[b].some(v => y.includes(v))) a.push(b);
      return a;
    }, []);
    
    console.log(res);

    对于您的评论 - 使用 var 和普通函数:

    var res = Object.keys(x).reduce(function (a, b) {
        if (x[b].some(function (v) {
                return y.indexOf(v) !== -1;
            })) a.push(b);
        return a;
    }, []);
    

    【讨论】:

    • 在推送到 a 之前,我会进行 && !a.includes(b) 检查 - 否则它将包含重复数据
    • 好主意@tymeJV,但由于对象键在定义上是唯一的,并且在第一次命中时会停止,我不认为可能存在重复。你能说在哪种情况下会发生吗?
    • 啊,是的,nvm - 它正在循环键。仅当您首先循环 y - nvm 时才会发生这种情况 :)
    • @Ackados letvar 的替代品,如果您打算在现代浏览器中使用它或使用转译器,您可以替换它。不过,您可以用 function() 替换箭头功能。编辑答案以使用普通函数和 var
    • 不错的方法,使用.reduce()
    【解决方案2】:

    您可以使用y 数组和Array#some 的映射来Array#filter Object#keys 的数组。

    var x = {
      "food": ['bacon', 'cheese', 'bread', 'tomato'],
      "utilities": ['plates', 'forks', 'spatulas'],
      "guests": ['john', 'matt', 'bill']
    };
    var y = ['bacon', 'tomato', 'forks'];
    var yMap = y.reduce(function(o, v) { // create a map to save iteration of y on each comparsion
      o[v] = true;
    
      return o;
    }, {});
    
    var result = Object.keys(x).filter(function(key) { // filter the keys
      return x[key].some(function(v) { // keep the key, if at least one item of the array is in the map
        return yMap[v];
      });
    });
    
    console.log(result);

    以及使用Set的ES6版本:

    const x = {
      "food": ['bacon', 'cheese', 'bread', 'tomato'],
      "utilities": ['plates', 'forks', 'spatulas'],
      "guests": ['john', 'matt', 'bill']
    };
    const y = ['bacon', 'tomato', 'forks'];
    const ySet = new Set(y);
    
    const result = Object.keys(x).filter((key) => x[key].some((item) => ySet.has(item)));
    
    console.log(result);

    【讨论】:

      【解决方案3】:

      您可以使用 .filter().some() 方法和Object.keys()

      function getContainerName(obj, values) {
        return Object.keys(obj).filter(function(key) {
          return y.some(function(v){
            return obj[key].indexOf(v) !== -1;
          })
        });
      }
      

      演示:

      var x = {
          "food": ['bacon', 'cheese', 'bread', 'tomato'],
          "utilities": ['plates', 'forks', 'spatulas'],
          "guests": ['john', 'matt', 'bill']
        },
        y = ['bacon', 'tomato', 'forks'];
      
      
      function getContainerName(obj, values) {
        return Object.keys(obj).filter(function(key) {
          return y.some(function(v){
            return obj[key].indexOf(v) !== -1;
          })
        });
      }
      console.log(getContainerName(x, y));

      【讨论】:

      • 如果我正确添加了代码,这会导致更快的速度。 jsperf.com/faster-array-naming
      • @Ackados 我认为这是因为这个的指令比其他的少,但它们只是解决问题的不同方法,选择其中一个取决于情况,你是否担心或与性能可读性无关。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-19
      • 2011-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-31
      相关资源
      最近更新 更多