简体   繁体   中英

JSON search loop stops after first hit

d Greetings, dear StackOverflow community! My question seems to be an easy one, but I just don't get it where I am doing it wrong.

So the thing is, I have a JSON with the following data:

var data = [{
  "id": 0,
  "friends": ["Mike", "John"],
  "enemies": ["Albert", "Amy"],
  "image": "https://link.com/1"
}, {
  "id": 1,
  "friends": ["Chad", "John"],
  "enemies": ["Lawrence", "Amy"],
  "image": "https://link.com/2"
}, {
  "id": 2,
  "friends": ["Craig", "John"],
  "enemies": ["Adam", "Amy"],
  "image": "https://link.com/3"
}, {
  "id": 3,
  "friends": ["Craig", "Bruce"],
  "enemies": ["Adam", "Scott"],
  "image": "https://link.com/4"
}];

Now I am trying to loop over this data using a user's input. For example, if a user types in "Adam", I would like to get the id of the object, where the poor Adam is presented in the enemies array.

So far I have came up with the following code:

function getObjectByEnemyName(name){
  for (var i = 0; i < data.length; i++) {               // In each object of the data array
    for (var m = 0; m < data[i].enemies.length; m++) { // Locate the enemies array and search through each of its elements
      if (data[i].enemies[m] == name) {              // If the m'th element of the enemies array in the i'th object of the data array equals to the entered string
        return data[i].id                                  // Return the id value of the data array's i'th object
      }
    }
  }
}


var found = getObjectByEnemyName("Adam");

Which works totally fine if I am searching, for example, for "Albert", because he is presented in the enemies array only once.

But when it comes to a query like "Adam", my function finds the first correct hit in the third object of the data array (with the id = 2) and refuses to go on, with the output being 2 , when there actually is another 'Adam' in the next object, and I want the result to be something like this:

['2', '3']

To achieve this type of behavior, I tried inserting more for and while loops inside the function I am using, but have failed miserably. I have also tried using some third-party node packages to search trough my data array, but have not succeeded as well.

And thus my question is: is there a way to tell my loop to continue looking for other matches and not to stop on the first correct hit? Any help will be appreciated.

PS: I myself control the look of the JSON data, so if the problem hides in the way it is composed, I can change it easily, just please let me know how.

Thank you very much for your kind attention!

Actually it's stopping at the first match because you're returning the first match...

If you want muliple matches, you can store them in an array and return the whole array once search has finished:

function getObjectByEnemyName(name) {
  var results = [];

  for (var i = 0; i < data.length; i++) { // In each object of the data array
    for (var m = 0; m < data[i].enemies.length; m++) { // Locate the enemies array and search through each of its elements
      if (data[i].enemies[m] == name) { // If the m'th element of the enemies array in the i'th object of the data array equals to the entered string
        results.push(data[i].id); // Return the id value of the data array's i'th object
      }
    }
  }

  return results;
}

BTW you can simplify your search as follows:

function getObjectsByEnemyName(name) {
     return data.filter(item => item.enemies.includes(name)).map(item => item.id);
}

Use Array#filter to get the items, which has the enemy you search ('Adam' in this case), then Array#map them to id :

 var data = [{"id": 0,"friends": ["Mike", "John"],"enemies": ["Albert", "Amy"],"image": "https://link.com/1"}, {"id": 1,"friends": ["Chad", "John"],"enemies": ["Lawrence", "Amy"],"image": "https://link.com/2"}, {"id": 2,"friends": ["Craig", "John"],"enemies": ["Adam", "Amy"],"image": "https://link.com/3"}, {"id": 3,"friends": ["Craig", "Bruce"],"enemies": ["Adam", "Scott"],"image": "https://link.com/4"}] var search = "Adam"; var result = data.filter(function(item) { return item.enemies.indexOf(search) !== -1; }).map(function(item) { return item.id; }); console.log(result); 

You can also do it in one pass using Array#reduce :

 var data = [{"id": 0,"friends": ["Mike", "John"],"enemies": ["Albert", "Amy"],"image": "https://link.com/1"}, {"id": 1,"friends": ["Chad", "John"],"enemies": ["Lawrence", "Amy"],"image": "https://link.com/2"}, {"id": 2,"friends": ["Craig", "John"],"enemies": ["Adam", "Amy"],"image": "https://link.com/3"}, {"id": 3,"friends": ["Craig", "Bruce"],"enemies": ["Adam", "Scott"],"image": "https://link.com/4"}] var search = "Adam"; var result = data.reduce(function(arr, item) { item.enemies.indexOf(search) === -1 || arr.push(item.id); return arr; }, []); console.log(result); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM