簡體   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