【问题标题】:Querying a JavaScript object查询 JavaScript 对象
【发布时间】:2019-04-10 18:54:02
【问题描述】:

给定以下三个对象,返回包含键值对的第一个对象的有效方法是什么?

var obj = {
  item1: {
    name: 'apple',
    color: 'red'
  },
  item2: {
    name: 'blueberry',
    color: 'blue'
  },
  item3: {
    name: 'cherry',
    color: 'red'
  }
};

var obj2 = {
  collection: [
    {
      item1: {
        name: 'apple',
        color: 'red'
      },
      item2: {
        name: 'blueberry',
        color: 'blue'
      },
      item3: {
        name: 'cherry',
        color: 'red'
      }
    }
  ]
};

var obj3 = {
  items: [
    {
      item1: {
        name: 'apple',
        color: 'red'
      }
    },
    {
      item2: {
        name: 'blueberry',
        color: 'blue'
      },
    },
    {
      item3: {
        name: 'cherry',
        color: 'red'
      }
    }
  ]
};

我希望以下三个语句得到相同的结果:

getObject(obj, 'color', 'red');
getObject(obj2, 'color', 'red');
getObject(obj3, 'color', 'red');

输出:

{
  name: 'apple',
  color: 'red'
}

这是我目前所拥有的,但我认为它在某处缺少一个闭包,因为它在函数调用自身时中断:

function getObject(arg, key, val) {
  if (typeof arg!=='object') return null;
  switch (Object.prototype.toString.call(arg)) {
    case '[object Array]':
      for (var i=0; i<arg.length; ++i) {
        getObject(arg[i], key, val);
      }
      break;
    case '[object Object]':
      for (var i in arg) {
        if (arg.hasOwnProperty(i)) {
          if (typeof arg[i]==='object') {
            getObject(arg[i], key, val);
          } else {
            if (i===key && arg[i]===val) {
              return arg;
            }
          }
        }
      }
      break;
  }
}

【问题讨论】:

标签: javascript object


【解决方案1】:

您可以使用此功能,它还将搜索更深嵌套的数据结构。

function getObject(obj, prop, value) {
    if (Object(obj) !== obj) return; // It is not an object
    if (obj[prop] === value) return obj; // Found it
    for (var key in obj) {
        var result = getObject(obj[key], prop, value);
        if (result) return result; // Found it
    }
}

var obj = {item1: {name: 'apple',color: 'red'},item2: {name: 'blueberry',color: 'blue'},item3: {name: 'cherry',color: 'red'}};
var obj2 = {collection: [{item1: {name: 'apple',color: 'red'},item2: {name: 'blueberry',color: 'blue'},item3: {name: 'cherry',color: 'red'}}]};
var obj3 = {items: [{item1: {name: 'apple',color: 'red'}},{item2: {name: 'blueberry',color: 'blue'},},{item3: {name: 'cherry',color: 'red'}}]};

console.log(getObject(obj, 'color', 'red'));
console.log(getObject(obj2, 'color', 'red'));
console.log(getObject(obj3, 'color', 'red'));

【讨论】:

  • 我其实最喜欢你的答案并最终使用它,但不幸的是我在看到你的解决方案之前接受了另一个答案。道歉。
  • 没问题。不是你必须这样做;但您知道:您始终可以将另一个答案标记为已接受,这将从您之前的选择中删除标记。但是,就像我在接受的答案下评论的那样:就目前而言,它有一个错误。
  • 我想迟到总比没有好。我发现您实际上可以取消选择已接受的答案。再次感谢这个非常简洁的解决方案!
【解决方案2】:

如果找到对象,您可以使用Array#some 进行快捷方式。

function getObject(object, key, value) {
    var result;
    if (!object || typeof object !== 'object') return;
    if (object[key] === value) return object;
    Object.values(object).some(v => result = getObject(v, key, value));
    return result;
}

var obj = { item1: { name: 'apple', color: 'red' }, item2: { name: 'blueberry', color: 'blue' }, item3: { name: 'cherry', color: 'red' } },
    obj2 = { collection: [{ item1: { name: 'apple', color: 'red' }, item2: { name: 'blueberry', color: 'blue' }, item3: { name: 'cherry', color: 'red' } }] },
    obj3 = { items: [{ item1: { name: 'apple', color: 'red' } }, { item2: { name: 'blueberry', color: 'blue' } }, { item3: { name: 'cherry', color: 'red' } }] };

console.log(getObject(obj, 'color', 'red'));
console.log(getObject(obj2, 'color', 'red'));
console.log(getObject(obj3, 'color', 'red'));
.as-console-wrapper { max-height: 100% !important; top: 0; }

【讨论】:

    【解决方案3】:

    您在getObject 中的方法是可以的,但是,作为一般方法,您应该为每个所有人转换数组。您可以使用函数map 来为查找过程准备数组。

    函数find根据特定谓词“找到”对象。

    这是假设索引与键 -&gt; 索引 i==0 -&gt; items1 等相关。

    var obj = {item1: {name: 'apple',color: 'red'},item2: {name: 'blueberry',color: 'blue'},item3: {name: 'cherry',color: 'red'}};
    var obj2 = {collection: [{item1: {name: 'apple',color: 'red'},item2: {name: 'blueberry',color: 'blue'},item3: {name: 'cherry',color: 'red'}}]};
    var obj3 = {items: [{item1: {name: 'apple',color: 'red'}},{item2: {name: 'blueberry',color: 'blue'},},{item3: {name: 'cherry',color: 'red'}}]};
    
    let getObject = (o, key, value) => o.find(obj => obj[key] === value);
    
    console.log(getObject(Object.values(obj), 'color', 'red'));
    console.log(getObject(obj2.collection.map((o, i) => o[`item${i+1}`]), 'color', 'red'));
    console.log(getObject(obj3.items.map((o, i) => o[`item${i+1}`]), 'color', 'red'));
    .as-console-wrapper { min-height: 100%; }

    【讨论】:

    • 谢谢你,@Ele。虽然我很欣赏这个解决方案的简洁性,但我现在不能使用它,因为 (1) 代码库在 ES5 上是标准化的,并且 (2) 使用这个辅助函数的其他开发人员不会知道 .map()在适当的时候。
    • @thdoan 没问题!
    • @thdoan,我只是偶然发现了这条评论:代码库是在 ES5 上标准化的。如果 ES5 是一个要求,那么应该在问题中明确提及。
    【解决方案4】:

    您可以递归调用该函数以到达没有任何对象成员的对象并通过键和值对其进行过滤:

    function getObject(obj, k, v) {
        for (var key in obj) {
            if (typeof obj[key] === 'object') {
                return getObject(obj[key], k, v);
            } else if (key === k && obj[key] === v) {
                return(obj);
            }
        }   
    }
    
    var obj = {
      item1: {
        name: 'apple',
        color: 'red'
      },
      item2: {
        name: 'blueberry',
        color: 'blue'
      },
      item3: {
        name: 'cherry',
        color: 'red'
      }
    };
    
    var obj2 = {
      collection: [
        {
          item1: {
            name: 'apple',
            color: 'red'
          },
          item2: {
            name: 'blueberry',
            color: 'blue'
          },
          item3: {
            name: 'cherry',
            color: 'red'
          }
        }
      ]
    };
    
    var obj3 = {
      items: [
        {
          item1: {
            name: 'apple',
            color: 'red'
          }
        },
        {
          item2: {
            name: 'blueberry',
            color: 'blue'
          },
        },
        {
          item3: {
            name: 'cherry',
            color: 'red'
          }
        }
      ]
    };
    console.log(getObject(obj, 'color', 'red'));
    console.log(getObject(obj2, 'color', 'red'));
    console.log(getObject(obj3, 'color', 'red'));

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-26
      • 1970-01-01
      • 2016-12-04
      • 2023-03-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-05
      相关资源
      最近更新 更多