如何检查对象中是否包含至少一个键,其值包含JavaScript中的子字符串?

如何检查对象中是否包含至少一个键,其值包含JavaScript中的子字符串?

问题描述:

我想编写一个检查对象是否具有至少一个包含子字符串的值的函数.这样的东西(伪代码):

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

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

我的对象的完整结构(

因此,对于以下用户:

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)应该返回true,因为在bio中找到了子字符串"bi":这是我的bi o". userMatches('324d,user)同样应该返回false.但是,usermatches('blocks', user)应该返回false,因为子字符串仅在键之一中找到,而不在值之一中找到.

, userMatches('bi', user) should return true because the substring 'bi' is found in the bio: 'this is my bio'. userMatches('324d, user) should likewise return false. usermatches('blocks', user) should, however, return false because the substring is only found in one of the keys, not one of the values.

我正在使用的对象看起来像这样(猫鼬模式):

The objects I'm working it look like this (the 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
    }
}

到目前为止,我发现最好的方法是将对象外的所有键分解,然后使用mapincludes,如下所示.

The best way of doing this I've found so far is destructuring all the keys that are strings off the object, and then using map and includes, like the function below.

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)并获得一个布尔值,那将是非常好的.提前非常感谢!

This is, however, really annoying (and probably terribly inefficient, too), as the objects I'm working with are really large. It'd be really nice if i could just call userMatchesText(text, user) and get a Boolean value. Thanks a lot in advance!

此外,请注意,我并没有销毁所有字符串(String).该功能的目的是根据搜索查询过滤用户,我认为让用户通过自己的生物,身份证等为其他用户服务可能没有太大意义,而只能通过其各种名字"来搜索其他用户. '.

Also, note I am not destructuring off all the keys that are Strings. The purpose of this function is to filter users based on a search query, and I figured it perhaps doesn't make too much sense to let users serch for other users by their bio, id etc. but rather, only by their various 'names'.

您可以使用递归函数来遍历整个对象.只需确保该对象没有任何循环引用即可.

You can do this with a recursive function to traverse the entire object. Just make sure that the object doesn't have any circular references...

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));