簡體   English   中英

基於多個鍵值對搜索對象數組的優化方法

[英]Optimized way to search an object array based on multiple key-value pairs

我寫了一個通用擴展方法,它將返回一個匹配所有給定搜索條件(lookUpArray)的項目。 這是Demo

/***************************Extension Method****************************/

    var utils = {};
            // Could create a utility function to do this
            utils.searchInArray = function (lookUpArray, caseSensitiveSearch) {
                if (!lookUpArray || lookUpArray.length <= 0)
                    return null;

                caseSensitiveSearch = caseSensitiveSearch || false;
                var self = this;
                var item = null;
                for (var index = 0; index < self.length; index++) {
                    item = self[index];
                    var exist = true;
                    for (var i = 0; i < lookUpArray.length; i++) {
                        if (item[lookUpArray[i].key] === lookUpArray[i].value) {
                            exist = exist * true;
                        } else { exist = exist * false; }
                    }
                    if (exist)
                        return item;
                };
                return exist ? item : null;
            };

            // or we could create a function on the Array prototype indirectly
            Array.prototype.excSearchObjArrayForKeyValue = utils.searchInArray;



/***************************Extension Method****************************/


        var inputObjectArray= [
            { emailType: 'primary', id: 1, username: 'saurabh', email: 'test@gmail.com', phone: '123' },
            { emailType: 'additional', id: 2, email: 'test2@gmail.com' },
            { emailType: 'additional', id: 2, email: 'test2@gmail.com', username:'spp' }
        ];

        //Below is the search criterion array. Extension method should return only that object which 
        //matches complete below lookUpArray
        var lookUpArray = [{ key: 'emailType', value: 'additional' }, { key: 'id', value: 2 }];

        var result = inputObjectArray.excSearchObjArrayForKeyValue(lookUpArray);
        console.log(result);

有沒有可能優化(性能)上面的搜索?

這取決於您的使用案例。 如果您將經常運行搜索功能(與修改數組的頻率相比),並且如果您可以搜索有限數量的可能鍵,則可能會發現創建和維護類似索引的結構是值得的。 現在你的查找是一個O(m*n)操作,其中m是鍵的數量, n是數組中的項目數。 有了適當的數據結構,查找可以成為O(m)操作。 由於我猜測n到目前為止可能是更大的數字,這可以使搜索范圍更有效率。

如果這樣做沒有意義,那么你至少應該縮短你的內循環。

            var self = this;
            for (var index = 0; index < self.length; index++) {
                var item = self[index];
                var matches = true;
                for (var i = 0; i < lookUpArray.length; i++) {
                    var lookUpItem = lookUpArray[i];
                    if (item[lookUpItem.key] !== lookUpItem.value) {
                        matches = false;
                        break;
                    }
                }
                if(matches) {
                    return item;
                }
            };
            return null;

或者,正如nnnnnn建議的那樣,你可以用標簽更簡潔地完成同樣的事情:

            var self = this;
            outer:
            for (var index = 0; index < self.length; index++) {
                var item = self[index];
                for (var i = 0; i < lookUpArray.length; i++) {
                    var lookUpItem = lookUpArray[i];
                    if (item[lookUpItem.key] !== lookUpItem.value) {
                        continue outer;
                    }
                }
                return item;
            };
            return null;

如果您使用的是ES6,您甚至可以利用.find().every()函數。

            var self = this;
            return self.find(item => 
                lookUpArray.every(lookUpItem => 
                    item[lookUpItem.key] === lookUpItem.val));

我建議不要將此方法添加到Array原型中。 我只是把它變成一種實用方法。

您可以使用Array.prototype.filterArray.prototype.every等數組函數,而不是自己迭代項目:

var utils = {
  searchInArray: function(targetArray, lookupArray, caseSensitiveSearch) {
    return targetArray.filter(function(x) {
      return lookupArray.every(function(lookup) {
        if (x[lookup.key] === undefined)
          throw new Error('No ' + lookup.key + ' property in object ' + x);

        if (typeof x[lookup.key] !== typeof lookup.value)
          throw new Error('Type mismatch on property ' + lookup.key ' + in object ' + x);

        if (typeof lookup.value === 'string' && caseSensitiveSearch)
          return x[lookup.key].toLowerCase() === lookup.value.toLowerCase();
        else
          return x[lookup.key] === lookup.value;
      });
    });
  }
};

工作演示片段:

 var utils = { searchInArray: function(targetArray, lookupArray, caseSensitiveSearch) { return targetArray.filter(function(x) { return lookupArray.every(function(lookup) { if (x[lookup.key] === undefined) throw new Error('No ' + lookup.key + ' property in object ' + x); if (typeof x[lookup.key] !== typeof lookup.value) throw new Error('Type mismatch on property ' + lookup.key ' + in object ' + x); if (typeof lookup.value === 'string' && caseSensitiveSearch) return x[lookup.key].toLowerCase() === lookup.value.toLowerCase(); else return x[lookup.key] === lookup.value; }); }); } }; var inputObjectArray = [ { emailType: 'primary', id: 1, username: 'saurabh', email: 'test@gmail.com', phone: '123' }, { emailType: 'additional', id: 2, email: 'test2@gmail.com' }, { emailType: 'additional', id: 2, email: 'test2@gmail.com', username: 'spp' } ]; var lookUpArray = [{ key: 'emailType', value: 'aDdItIoNaL' }, { key: 'id', value: 2 }]; var result = utils.searchInArray(inputObjectArray, lookUpArray, true); console.log(result); 

您可以使用Arrays.find函數。

如果數組中的元素滿足提供的測試函數,則find()方法返回數組中的值。 否則返回undefined。

看看這個例子:

var inventory = [
    {name: 'apples', quantity: 2},
    {name: 'bananas', quantity: 0},
    {name: 'cherries', quantity: 5}
];

function findCherries(fruit) { 
    return fruit.name === 'cherries';
}

console.log(inventory.find(findCherries)); // { name: 'cherries', quantity: 5 }

您也可以編寫自定義邏輯,例如。 找到素數:

function isPrime(element, index, array) {
  var start = 2;
  while (start <= Math.sqrt(element)) {
    if (element % start++ < 1) {
      return false;
    }
  }
  return element > 1;
}

console.log([4, 6, 8, 12].find(isPrime)); // undefined, not found
console.log([4, 5, 8, 12].find(isPrime)); // 5

如果有幫助,請標記正確。

要獲得第一個匹配的obj,您可以嘗試這個

utils.searchInArray = function(lookUpArray, caseSensitiveSearch) {
    if (!lookUpArray || lookUpArray.length <= 0)
      return null;
    caseSensitiveSearch = caseSensitiveSearch || true;
    var self = this;
    return self.find(function(obj) {
      return lookUpArray.every(function(lookup) {
        if (typeof lookup.value === 'string' && caseSensitiveSearch)
          return obj[lookup.key].toLowerCase() === lookup.value.toLowerCase();
        else
          return obj[lookup.key] === lookup.value;
      });

    });
  };

獲取所有匹配的對象

utils.searchInArray = function(lookUpArray, caseSensitiveSearch) {
    if (!lookUpArray || lookUpArray.length <= 0)
      return null;
    caseSensitiveSearch = caseSensitiveSearch || true;
    var self = this;
    return self.filter(function(obj) {
      return lookUpArray.every(function(lookup) {
        if (typeof lookup.value === 'string' && caseSensitiveSearch)
          return obj[lookup.key].toLowerCase() === lookup.value.toLowerCase();
        else
          return obj[lookup.key] === lookup.value;
      });

    });
  };

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM