繁体   English   中英

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

[英]How can I check if an object contains at least one key whose value contains a substring in JavaScript?

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

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因为子字符串只能在其中一个键中找到,而不是其中一个键。

我正在使用的对象看起来像这样(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 ,就像下面的函数一样。

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)并获得布尔值userMatchesText(text, user)那将是非常好的。 非常感谢提前!

另外,请注意我并没有解析所有的字符串键。 此功能的目的是根据搜索查询过滤用户,我认为让用户通过他们的bio,id等为其他用户提供服务也许没有多大意义,而只是通过他们的各种名称”。

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

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

纯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; } }()); 

这应该做的伎俩:

(见代码下面的解释)

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

findInObject函数完成繁重的工作。 你提供一个谓词(这是一个根据输入“通过”返回truefalse的函数)和一个要搜索的对象。 它在对象中的每个键上运行谓词,如果提供的对象包含对象,则以递归方式运行谓词。 它应该停止搜索它是否匹配。 否则,它会遍历整个对象。

userContainsText函数使用findInObject 它提供了一个谓词,用于检查所获得的任何字符串的内容。 (任何其他类型都未通过测试)。 此函数接受要查找的文本和要搜索的用户对象(尽管从技术上讲,这可以由任何对象,而不是“用户”对象)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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