How to check if an object contains at least one key whose value contains a substring in JavaScript?

I want to write a function that checks if an object has at least one value containing a substring. Something like this (pseudocode):

const userMatchesText = (text, user) => user.includes(text);

The full structure of my objects (

So for the user as shown below:

const user = {
    id: '123abc',
    info: {
        age: 12,
        bio: 'This is my bio' 
    },
    social: {
        chatName: 'Chris',
        friends: ['friend1', 'other friend'],
        blocks: ['Creep']
    }
    //Etc. The objects I'm working with contain nested objects and arrays, etc.
}

, userMatches('bi', user)Should return true, because the substring "bi" is located in the bio: "This is my bio". userMatches ('324d, user) should also return false. usermatches('blocks', user)should return false, because the substring is in only one of the keys, and not in one of the values.

The objects I'm working with look like this (Mongoose schema):

{
    account  : {
        dateOfCreation : Number
    },
    social   : {
        chatName         : String,
        friends          : [ { type: String } ],
        blocks           : [ { type: String } ],
        sentRequests     : [ { type: String } ],
        recievedRequests : [ { type: String } ],
        threads          : [ { type: String } ]
    },
    info     : {
        age            : Number,
        bio            : String,
        displayName    : String,
        profilePicture : String,
        subjects       : {
            tutor   : [
                {
                    subject : String,
                    level   : String
                }
            ],
            student : [
                {
                    subject : String,
                    level   : String
                }
            ]
        }
    },
    facebook : {
        id         : String,
        firstName  : String,
        middleName : String,
        fullName   : String,
        lastName   : String
    }
}

, , - , , map includes, .

const doesUserMatchText = (user, text) => {
    const { social: { chatName }, info: { displayName }, facebook: { firstName, middleName, lastName } } = user;
    const possibleMatches = [ chatName, displayName, firstName, middleName, lastName ];
    let match = false;
    possibleMatches.map(possibleMatch => {
        if (possibleMatch.includes(text)) {
            return (match = true);
        }
    });
};

, , (, , ), , , . , userMatchesText(text, user) . !

, , , . - , , , , , .., "".

+4
3

. , ...

const user = {
    id: '123abc',
    info: {
        age: 12,
        bio: 'This is my bio' 
    },
    social: {
        chatName: 'Chris',
        friends: ['friend1', 'other friend'],
        blocks: ['Creep']
    }
    //Etc. The objects I'm working with contain nested objects and arrays, etc.
};

function userMatchesText(text, user) {
    if (typeof user === "string") return user.includes(text);
    return Object.values(user).some(val => userMatchesText(text, val));
}

console.log(userMatchesText("bi", user));
console.log(userMatchesText("other fri", user));
console.log(userMatchesText("zzz", user));
Hide result
+3

JavaScript. , , true.

, false, .

(function() {
  var user = {
    id: '123abc',
    info: {
      age: 12,
      bio: 'This is my bio'
    },
    social: {
      chatName: 'Chris',
      friends: ['friend1', 'other friend'],
      blocks: ['Creep']
    }
    //Etc. The objects I'm working with contain nested objects and arrays, etc.
  };

  console.log('userMatches(\'bi\', user): ' + userMatches('bio', user));
  console.log('userMatches(\'324d\', user): ' + userMatches('324d', user));
  console.log('usermatches(\'blocks\', user) ' + userMatches('blocks', user));

  function userMatches(str, obj) {
    var queue = [];
    for (var k in obj) {
      if (obj.hasOwnProperty(k)) {
        if (typeof obj[k] === 'string') {
          if (obj[k].indexOf(str) !== -1) {
            return true;
          }
        } else {
          queue.push(obj[k]);
        }
      }
    }
    if (queue.length) {
      for (var i = 0; i < queue.length; i++) {
        if (userMatches(str, queue[i])) {
          return true;
        }
      }
    }
    return false;
  }
}());
Hide result
+2

:

(. )

const findInObject = (predicate, object) => {
  if (typeof object !== 'object') {
    throw new TypeError('Expected object but got ' + typeof object)
  }
  
  for (let key in object) {
    const value = object[key]
    switch (typeof value) {
      case 'object':
        if (findInObject(predicate, value))
          return true
      default:
        if (predicate(value))
          return true
    }
  }
  return false
}

const userContainsText = (text, user) => 
  findInObject(
    val => {
      if (typeof val !== 'string')
        return false
        
      return val.includes(text)
    },
    user
  )
  
const user = {
    id: '123abc',
    info: {
        age: 12,
        bio: 'This is my bio' 
    },
    social: {
        chatName: 'Chris',
        friends: ['friend1', 'other friend'],
        blocks: ['Creep']
    }
}

console.log(userContainsText('Chris', user))
Hide result

findInObject . (, true false , "" ), . , , . , . .

Function userContainsTextuses findInObject. It provides a predicate that checks the contents of any rows it receives. (Any other type does not pass the test). This function accepts the text to be searched and the user object for search (although technically it can be any object, not just a "user" object).

+1
source

Source: https://habr.com/ru/post/1694371/