在对象数组中寻找匹配的属性和值对

3

我正在尝试解决一个freeCodeCamp的练习,但卡住了。这个练习的目标是:编写一个函数,查找包含匹配属性和值对(第二个参数)的所有对象,并返回一个对象数组(第一个参数)。如果要将源对象的每个属性和值对包含在集合中的对象中,则必须包含在返回的数组中。
所以我的做法是,先创建一个集合的键值对数组,再创建一个源的键值对数组。然后我嵌套了for循环以查找匹配的键,如果找到了这些键,则比较属性。
但不知何故,我的代码没有返回任何匹配项。
var collection = [{
  first: "Romeo",
  last: "Montague"
}, {
  first: "Mercutio",
  last: null
}, {
  first: "Tybalt",
  last: "Capulet"
}];
var source = {
  last: "Capulet"
};

var collectionKeys = [];
for (var i = 0; i < collection.length; i++) {
  collectionKeys.push(Object.keys(collection[i]));
}
var sourceKeys = Object.keys(source);

//for every key pair
for (var t = 0; t < collectionKeys.length; t++) {
  //for every key in key pair
  for (var x = 0; x < collectionKeys[t].length; x++) {
    //for every key in search
    for (var y = 0; y < sourceKeys.length; y++) {
      //see if a key matches
      if (sourceKeys[y] == collectionKeys[t][x]) {
        //see if the value matches
        if (collection[collectionKeys[t][x]] == source[sourceKeys[y]]) {
          console.log(collection[t]);
        } else {
          console.log("value not found");
        }
      } else {
        console.log("key not found");
      }
    }
  }
}

有人能指出我做错了什么吗?
我还创建了一个JSfiddle,如果你想玩一下的话。

更好的变量名称会为您服务良好,包括创建一些临时变量以更好地表达您正在处理的内容。例如,sourcePropertyValuesource[sourceKeys[y]]更易于阅读。如果您已经学习了函数,那么这个算法就需要被分解成至少两个函数。例如,我想要一个函数仅用于确定两个对象是否匹配。 - Jack A.
6个回答

3

我也曾经被这个问题困扰了好几个小时,后来我偶然发现了一些资源可以帮助我。

我发现,与其使用嵌套的for循环,我可以使用内置的循环方法来大大简化我的代码。

以下是我找到的解释来源:

https://github.com/Rafase282/My-FreeCodeCamp-Code/wiki/Bonfire-Where-art-thou

function where(collection, source) {
  var arr = [];
  var keys = Object.keys(source);
  // Filter array and remove the ones that do not have the keys from source.
  arr = collection.filter(function(obj) {
    //Use the Array method every() instead of a for loop to check for every key from source.
    return keys.every(function(key) {
      // Check if the object has the property and the same value.
      return obj.hasOwnProperty(key) && obj[key] === source[key];
    });
  });

  return arr;
}

2

在声明时更明确 - 有助于更轻松地阅读代码:

var sourceKeys = Object.keys(source),
    i = 0, 
    j = 0,
    collectionLength = collection.length,
    sourceKeysLength = sourceKeys.length;

while (i < collectionLength) {
    j = 0;
    while (j < sourceKeysLength) {
        if (sourceKeys[j] in collection[i] && source[sourceKeys[j]] === collection[i][sourceKeys[j]]) {
            console.log('found one!');
        }
        j++;
    }
    i++;
}

https://jsfiddle.net/fullcrimp/1cyy8z64/


1

这里提供一些清晰易懂且循环次数较少的见解。

一些新的 JavaScript 函数,如 some、filter、map,非常方便,可以使代码更加整洁。

function whatIsInAName(collection, source) {
  // What's in a name?
  var arr = [];
  // Only change code below this line
  collection.some(function(obj){
      var sk = Object.keys(source); //keys of source object
      var sv = Object.values(source); //values of source object
      var temp = 0; 
      for(i=0;i<sk.length;i++){ // run until the number of source properties length is reached.
        if(obj.hasOwnProperty(sk[i]) && obj[sk[i]] === sv[i]){ // if it has the same properties and value as parent object from collection 
          temp++; //temp value is increased to track if it has matched all the properties in an object
        }
      }
      if(sk.length === temp){ //if the number of iteration has matched the temp value 
        arr.push(obj);
        temp = 0; // make temp zero so as to count for the another object from collection
      }
  })
  // Only change code above this line
  return arr;
}

0

这就是我在同一个问题上得出的结论。

function whereAreYou(collection, source) {
  // What's in a name?

  // Only change code below this line

  var arr = [];
  var validObject;

// check each object
  for  (var each_object in collection ){
    validObject = true;
    for (var key in source ){
      if ( collection[each_object].hasOwnProperty(key)){
        if ( collection[each_object][key] != source[key]){ 
       // if no valid key
       validObject = false;
     } 
   } else {
    // if no valid value
     validObject = false;
   }
 }
  // otherwise, give it a green light
 if(validObject){
  arr.push(collection[each_object]);
  }   
}
return arr;

}

0

var collection = [{
  first: "Romeo",
  last: "Montague"
}, {
  first: "Mercutio",
  last: null
}, {
  first: "Tybalt",
  last: "Capulet"
}];
var source = {
  last: "Capulet"
};

var collectionKeys = [];
for (var i = 0; i < collection.length; i++) {
  collectionKeys.push(Object.keys(collection[i]));
}
var sourceKeys = Object.keys(source);

//for every key pair
for (var t = 0; t < collectionKeys.length; t++) {
  //for every key in key pair
  for (var x = 0; x < collectionKeys[t].length; x++) {
    //for every key in search
    for (var y = 0; y < sourceKeys.length; y++) {
      //see if a key matches
      if (sourceKeys[y] == collectionKeys[t][x]) {
        if (collection[t][collectionKeys[t][x]] == source[sourceKeys[y]]) {
         alert(collection[t].first+ " "+collection[t].last);
        } else {
          console.log("value not found");
        }
      } else {
        console.log("key not found");
      }
    }
  }
}

collection[collectionKeys[t][x]]改为collection[t][collectionKeys[t][x]]。在控制台中,collection[collectionKeys[t][x]]会返回undefined


0
function whatIsInAName(collection, source) {
  const keyCount = Object.keys(source).length;
  return collection.filter((item) => {
    return Object.entries(item).reduce((acc, [key, value], _, arr) => {
      if (keyCount > arr.length) {
        acc = false;
      } else if (keyCount === arr.length && !source[key]) {
        acc = false;
      } else if (source[key] && source[key] !== value) {
        acc = false;
      }
      return acc;
    }, true)
  })
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接