В javascript, как бы вы построить метод, который сравнивает значение A со значением B - PullRequest
1 голос
/ 18 февраля 2009

У меня есть массив объектов, что-то вроде этого:

var myArray = [
   { 'name' : 'some name', id: 23131, 'has' : ['dogs'] },
   { 'name' : 'some name 2', id: 8678, 'has' : ['dogs', 'cats'] },
   { 'name' : 'some name 3', id: 2125 , 'has' : ['donkeys', 'goats']},
   { 'name' : 'some name 4', id: 90867, 'has' : ['parrots', 'treasure'] },
   { 'name' : 'some name 5', id: 435458, 'has' : undefined },
];

И я хочу получить конкретные элементы, которые соответствуют определенным критериям. Например, человек, имя которого содержит число 5, а идентификатор - 435458. Или человек, у которого есть попугай, или козел, или оба.

Метод, который я пытаюсь построить, принимает два аргумента: значение A и значение B. Значение A - это объект, например { 'name' : '5' } или { 'name' : /5/ } или { 'name' : 5 } или {'has': 'goats'}, и значение B является объектом для сопоставления, например myArray.

Метод быстро становится довольно сложным, и я чувствую, что мой код не настолько эффективен и действенен, как мог бы.

Я думаю, что лучший способ добиться этого - циклически проходить через объекты и массивы, которые передаются и обнаруживаются (массив myArray, has), и вызывать его самостоятельно, пока не останется только два значения string / number / regexp для сравнивать с Но я не совсем уверен, как лучше всего этого достичь. Или это не лучший путь? Кроме того, скорость является важным критерием успеха.

Приветствия

Редактировать: http://jsbin.com/ediye/edit содержит функцию, которую я сейчас использую, и я думаю, что она работает, как описано выше, но довольно медленно для больших наборов данных.

Ответы [ 3 ]

1 голос
/ 27 февраля 2009

Хорошо, я вижу, что довольно много людей заинтересованы в этом, поэтому вот что у меня есть до сих пор:

var filter = function(what,where) {
    var sameArrays = function(arr,arr1) {
        var al = arr.length, bl = arr1.length;
        if (al !== bl || al === 0 || bl === 0) { return; }
        for (var i = al - 1; i >= 0; i--){
            if (!match(arr[i], arr1[i])) { return; }
        }
        return arr1;
    };

    var sameObjects = function(obj,obj1) {
        for (var i in obj) {
            if(!obj1.hasOwnProperty(i)){return;}
            if (!match(obj[i],obj1[i])) {return;}
        }
        return obj1;
    };

    var inArray = function(value,obj) {
        var r = [],
            m = match;

        for (var i = obj.length - 1; i >= 0; i--){
            var item = obj[i];
            if( m(value,item) ) {
                r.push( item );
            }
        };

        return (r.length) ? r : undefined ;
    };

    var inObject = function(value,obj) {
        var r = [],
            m = match;

        for(var i in obj){
            var item = obj[i];
            if( m(value,item) ) {
                r.push( item );
            }
        };

        return (r.length) ? r : undefined ;
    };

    var inString = function(value,string) { 
        var valueConstructor = value.constructor;

        if( valueConstructor === RegExp) {
            return (value.test(string)) ? string : undefined ; }

        else if( valueConstructor === Function && value(string) === true ) {
            return string; }

    };

    var match = function(a,b) {
        if(typeof a === 'undefined' || typeof b === 'undefined' || a === null || b === null) {
            return; }

        if (a == b) { 
            return b;}

        var vc = a.constructor,
            oc = b.constructor;

    // Cannot compare array or object to a string or a number
        if( (vc === Array || vc === Object) && (oc === String || oc === Number) ) {
            return; }

        if( oc === Array && vc === Array ) {
            return sameArrays(a,b); }
        else if(oc === Array) {
            return inArray(a,b); }
        else if (oc === Object && vc === Object) {
            return sameObjects(a,b); }
        else if (oc === Object) {
            return inObject(a,b); }         
        else if (vc === Object || vc === Array) {
            return; }
        else if (oc === String || oc === Number){
            return inString(a,b); }

    };

    return match(what,where);
};

Что позволяет сделать следующее:

var b = [
   { 'name' : 'some name', age: 23, id: 0, 'has' : ['dogs'] },
   { 'name' : 'some name 2', age:24, id: 1, 'has' : ['dogs', 'cats'] },
   { 'name' : 'some name 3', age: 25, id: 2 , 'has' : ['donkeys', 'goats']},
   { 'name' : 'some name 4', age:26, id: 3, 'has' : ['parrots', 'treasure'] },
   { 'name' : 'some name 5', age:27, id: 4, 'has' : undefined }
];

filter({ age:23 },b)

filter({ age:'24' },b)

filter({ name: /\d$/ },b)

filter('dogs',b)

filter({ has: 'goats' },b)

Это часть какой-то библиотеки js, над которой я работал, поэтому, если вы обнаружите, что работаете с json + dom, попробуйте поискать код Google для jdatastore .

0 голосов
/ 18 февраля 2009

Мне кажется, что те вещи, которые вы пытаетесь сделать, идеально соответствуют какому-то запросу к базе данных.

Для эффективности вам лучше всего переместить этот код выбора на сервер, где вы можете использовать SQL-запрос.

0 голосов
/ 18 февраля 2009

Вам просто нужно отфильтровать массив.

var matchedItems = myArray.filter(function(item) {
    return (item.name.indexOf("5") !== -1) && (item.id === 435458);
});

К сожалению, метод фильтрации - JS 1.6 и пока не поддерживается в IE. Тем не менее, почти все фреймворки имеют своего рода механизм фильтрации, который использует аналогичную идею. Если вы не хотите использовать фреймворк, вот решение с сайта Mozilla :

if (!Array.prototype.filter)
{
  Array.prototype.filter = function(fun /*, thisp*/)
  {
    var len = this.length;
    if (typeof fun != "function")
      throw new TypeError();

    var res = new Array();
    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in this)
      {
        var val = this[i]; // in case fun mutates this
        if (fun.call(thisp, val, i, this))
          res.push(val);
      }
    }

    return res;
  };
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...