web-dev-qa-db-fra.com

Javascript: comment filtrer un tableau d'objets en fonction d'attributs?

J'ai le tableau JavaScript suivant d'objets de propriété immobilière:

var json = {
    'homes': [{
            "home_id": "1",
            "price": "925",
            "sqft": "1100",
            "num_of_beds": "2",
            "num_of_baths": "2.0",
        }, {
            "home_id": "2",
            "price": "1425",
            "sqft": "1900",
            "num_of_beds": "4",
            "num_of_baths": "2.5",
        },
        // ... (more homes) ...     
    ]
}

var xmlhttp = eval('(' + json + ')');
homes = xmlhttp.homes;

Ce que je voudrais faire est de pouvoir effectuer un filtre sur l'objet pour renvoyer un sous-ensemble d'objets "de base".

Par exemple, je veux pouvoir filtrer en fonction de: price, sqft, num_of_beds et num_of_baths.

Question: Comment puis-je effectuer quelque chose en JavaScript comme le pseudo-code ci-dessous:

var newArray = homes.filter(
    price <= 1000 & 
    sqft >= 500 & 
    num_of_beds >=2 & 
    num_of_baths >= 2.5 );

Notez que la syntaxe ne doit pas nécessairement être exactement comme ci-dessus. C'est juste un exemple.

356
JGreig

Vous pouvez utiliser la méthode Array.prototype.filter :

var newArray = homes.filter(function (el) {
  return el.price <= 1000 &&
         el.sqft >= 500 &&
         el.num_of_beds >=2 &&
         el.num_of_baths >= 2.5;
});

Exemple en direct:

var obj = {
    'homes': [{
            "home_id": "1",
            "price": "925",
            "sqft": "1100",
            "num_of_beds": "2",
            "num_of_baths": "2.0",
        }, {
            "home_id": "2",
            "price": "1425",
            "sqft": "1900",
            "num_of_beds": "4",
            "num_of_baths": "2.5",
        },
        // ... (more homes) ...     
    ]
};
// (Note that because `price` and such are given as strings in your object,
// the below relies on the fact that <= and >= with a string and number
// will coerce the string to a number before comparing.)
var newArray = obj.homes.filter(function (el) {
  return el.price <= 1000 &&
         el.sqft >= 500 &&
         el.num_of_beds >= 2 &&
         el.num_of_baths >= 1.5; // Changed this so a home would match
});
console.log(newArray);

Cette méthode fait partie de la nouvelle norme ECMAScript 5th Edition et peut être trouvée sur presque tous les navigateurs modernes.

Pour IE, vous pouvez inclure la méthode suivante pour la compatibilité:

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

    var res = [];
    var thisp = arguments[1];
    for (var i = 0; i < len; i++) {
      if (i in this) {
        var val = this[i];
        if (fun.call(thisp, val, i, this))
        res.Push(val);
      }
    }
    return res;
  };
}
555
CMS

Vous pouvez essayer d’utiliser un framework comme jLinq - Voici un exemple de code permettant d’utiliser jLinq.

var results = jLinq.from(data.users)
.startsWith("first", "a")
.orEndsWith("y")
.orderBy("admin", "age")
.select();

Pour plus d'informations, vous pouvez suivre le lien http://www.hugoware.net/projects/jlinq

27
Rutesh Makhijani

Je préfère le framework Underscore. Il suggère de nombreuses opérations utiles avec des objets . Votre tâche:

var newArray = homes.filter(
    price <= 1000 & 
    sqft >= 500 &
    num_of_beds >=2 & 
    num_of_baths >= 2.5);

peut être écrasé comme:

var newArray = _.filter (homes, function(home) {
    return home.price<=1000 && sqft>=500 && num_of_beds>=2 && num_of_baths>=2.5;
});

J'espère que cela vous sera utile!

24
JuliaCesar

voici le violon qui fonctionne bien dans IE8 en utilisant la fonction jquery MAP

http://jsfiddle.net/533135/Cj4j7/

json.HOMES = $.map(json.HOMES, function(val, key) {
    if (Number(val.price) <= 1000
            && Number(val.sqft) >= 500
            && Number(val.num_of_beds) >=2
            && Number(val.num_of_baths ) >= 2.5)
        return val;
});
9

Vous pouvez le faire assez facilement - il y a probablement beaucoup d'implémentations parmi lesquelles vous pouvez choisir, mais c'est mon idée de base (et il existe probablement un format où vous pouvez itérer sur un objet avec jQuery, je n'arrive pas à y penser maintenant):

function filter(collection, predicate)
{
    var result = new Array();
    var length = collection.length;

    for(var j = 0; j < length; j++)
    {
        if(predicate(collection[j]) == true)
        {
             result.Push(collection[j]);
        }
    }

    return result;
}

Et ensuite, vous pouvez invoquer cette fonction comme suit:

filter(json, function(element)
{
    if(element.price <= 1000 && element.sqft >= 500 && element.num_of_beds > 2 && element.num_of_baths > 2.5)
        return true;

    return false;
});

De cette façon, vous pouvez appeler le filtre en fonction du prédicat que vous définissez, ou même filtrer plusieurs fois à l'aide de filtres plus petits. 

7
Tejs

Vous pouvez utiliser jQuery.grep () depuis jQuery 1.0:

$.grep(homes, function (h) {
  return h.price <= 1000
    && h.sqft >= 500
    && h.num_of_beds >= 2
    && h.num_of_baths >= 2.5
});
6
Akira Yamamoto

Vous pouvez implémenter vous-même une méthode de filtrage qui répond à vos besoins, voici comment:

function myfilter(array, test){
    var passedTest =[];
    for (var i = 0; i < array.length; i++) {
       if(test( array[i]))
          passedTest.Push(array[i]);
    }

    return passedTest;
}

var passedHomes = myfilter(homes,function(currentHome){
     return ((currentHome.price <= 1000 )&& (currentHome.sqft >= 500 )&&(currentHome.num_of_beds >=2 )&&(currentHome.num_of_baths >= 2.5));
});

J'espère que ça aide!

3
user4620852

Vous devriez vérifier OGX.List qui possède des méthodes de filtrage intégrées et étend le tableau javascript standard (ainsi que le regroupement, le tri et la recherche). Voici une liste des opérateurs pris en charge pour les filtres:

'eq' //Equal to
'eqjson' //For deep objects, JSON comparison, equal to
'neq' //Not equal to
'in' //Contains
'nin' //Doesn't contain
'lt' //Lesser than
'lte' //Lesser or equal to
'gt' //Greater than
'gte' //Greater or equal to
'btw' //Between, expects value to be array [_from_, _to_]
'substr' //Substring mode, equal to, expects value to be array [_from_, _to_, _niddle_]
'regex' //Regex match

Vous pouvez l'utiliser de cette façon

  let list = new OGX.List(your_array);
  list.addFilter('price', 'btw', 100, 500);
  list.addFilter('sqft', 'gte', 500);
  let filtered_list = list.filter();

Et vous pouvez ajouter autant de filtres que vous le souhaitez (un seul par propriété)

2
Eric

Ou vous pouvez simplement utiliser $.each (qui fonctionne aussi pour les objets, pas seulement les tableaux) et construire un nouveau tableau comme ceci:

var json = {
    'homes': [{
            "home_id": "1",
            "price": "925",
            "sqft": "1100",
            "num_of_beds": "2",
            "num_of_baths": "2.0",
        }, {
            "home_id": "2",
            "price": "1425",
            "sqft": "1900",
            "num_of_beds": "4",
            "num_of_baths": "2.5",
        },
        // ... (more homes) ...     
        {
            "home_id": "3-will-be-matched",
            "price": "925",
            "sqft": "1000",
            "num_of_beds": "2",
            "num_of_baths": "2.5",
        },
    ]
}

var homes = [];
$.each(json.homes, function(){
    if (this.price <= 1000
        && this.sqft >= 500
        && this.num_of_beds >= 2
        && this.num_of_baths >= 2.5
    ) {
        homes.Push(this);
    }
});
1
Nux
var filterHome = homes.filter(home =>
  return (home.price <= 999 &&
         home.num_of_baths >= 2.5 &&
         home.num_of_beds >=2 &&
         home.sqft >= 998));
console.log(filterHome);

Vous pouvez utiliser cette fonction lambda. Plus de détails peuvent être trouvés ici puisque nous filtrons les données en fonction de votre condition qui renvoie true ou false et que les données seront collectées dans un tableau différent afin que votre tableau actuel ne soit pas modifié. 

@JGreig S'il vous plaît examiner.

0
hardik beladiya
const x = JSON.stringify(data);
const y = 'search text';

const data = x.filter(res => {
        return(JSON.stringify(res).toLocaleLowerCase()).match(x.toLocaleLowerCase());
      });
0
Thức Trần

Je suis surpris que personne n'ait posté la réponse d'une ligne:

const filteredHomes = json.homes.filter(x => x.price <= 1000 && x.sqft >= 500 && x.num_of_beds >=2 && x.num_of_baths >= 2.5);

... et pour que vous puissiez le lire plus facilement:

const filteredHomes = json.homes.filter( x => 
  x.price <= 1000 && 
  x.sqft >= 500 && 
  x.num_of_beds >=2 && 
  x.num_of_baths >= 2.5
);
0
Lou Bagel