J'ai besoin de filtrer un tableau par 4 propriétés d'objet en fonction de l'entrée de l'utilisateur, mais parfois l'utilisateur peut choisir de n'entrer que 1, 2 ou 3 termes, ce qui donne des propriétés non définies par l'utilisateur.
const myTableData = [ { 'date': '2020-05-16', 'duration': 247, 'low_temp': 373.0, 'high_temp': 388.0, 'type': 'XD' }, { 'date': '2020-05-27', 'duration': 246, 'low_temp': 373.0, 'high_temp': 388.0, 'type': 'LB' }, { 'date': '2020-06-04', 'duration': 247, 'low_temp': 374.0, 'high_temp': 388.0, 'type': 'LB' } ]; export async function filter_click(event) { let newArray = myTableData.filter(function (el) { return el.duration === Number($w("#duration").value) && el.low_temp === Number($w("#lowtemp").value) && el.high_temp === Number($w("#hightemp").value) && el.type === $w("#type").value; }); $w("#table1").rows = newArray; }
Voir si même 1 des éléments d'entrée utilisateur n'est pas rempli, cela donne un indéfini qui renvoie un tableau vide.
Pourquoi je ne peux pas utiliser || au lieu de &&
Si j'utilise le OU '||' opérateur, il ne se limite pas à TOUTES les propriétés demandées par l'utilisateur. Exemple: si 'duration' est de 350 & 'type' est 'LB' et que l'utilisateur tape dans les deux, il ne retournera pas UNIQUEMENT les objets qui ont à la fois une durée de 350 et un type de LB, à la place il renverra des objets ayant l'un ou l'autre. p>
3 Réponses :
Cela vous aidera probablement beaucoup lorsque vous essayez de résoudre un problème, pour rendre votre code plus facile à lire. À l'heure actuelle, vous avez une ligne de retour massive qui est très difficile à lire et à comprendre.
Une fonction de filtrage doit simplement renvoyer true
(à tout moment) si l'élément évalué doit être inclus, et false (à tout moment) s'il doit être exclu. Ainsi, vous pouvez évaluer chacun de vos champs, un par un, pour voir s'il échoue à l'une des conditions requises et devrait être exclu , sur quoi vous renvoyez false. Sinon, à la fin de la fonction, si elle réussit tous les tests, vous savez qu'elle doit être incluse et retourner true
(le "cas de base"). Ce type de filtrage inverse où vous testez les observations à exclure plutôt que les observations à inclure peut souvent être beaucoup plus facile à écrire, à lire et à raisonner.
J'écrirais également la fonction de filtre elle-même comme une fonction séparée pour le rendre plus clair, plus lisible et plus facile à entretenir.
// Exclude compared item if it fails any of the "tests" // Otherwise include it (return true) function filterTable(el) { if (el.duration !== Number($w("#duration").value) || el.duration === undefined) { return false; } if (el.low_temp !== Number($w("#lowtemp").value) || el.low_temp === undefined) { return false; } // etc. for each field to be compared // Base case - by this point it has passed all tests and should be included return true; } export async function filter_click(event) { let newArray = myTableData.filter(filterTable); $w("#table1").rows = newArray; }
Que diriez-vous d'une boucle for et d'un tableau booléen?
for (i = 0; i<array.length; i++) if thing != array[i]: bool[i] = false for (each in bool): if each == false: do something;
Il serait avantageux d'expliquer votre réponse au lieu d'un pseudo-code très limité.
Quelques points
Array.filter()
Array.filter()
De cette façon, vous n'effectuez pas de recherches coûteuses et ne diffusez pas à chaque itération dans le filtre. Vous n'avez pas besoin de prendre en compte les propriétés à moins que le paramètre associé n'ait été inclus.
Extrait:
<input id="duration" value="246" /> <input id="lowtemp" value="373.0" /> <input id="hightemp" value="388.0" /> <input id="type" value="LB" /> <button id="filter">filter</button>
const myTableData = [{ 'date': '2020-05-16', 'duration': 247, 'low_temp': 373.0, 'high_temp': 388.0, 'type': 'XD' }, { 'date': '2020-05-27', 'duration': 246, 'low_temp': 373.0, 'high_temp': 388.0, 'type': 'LB' }, { 'date': '2020-06-04', 'duration': 247, 'low_temp': 374.0, 'high_temp': 388.0, 'type': 'LB' } ]; window.addEventListener('load', () => { // cache the elements to avoid expensive lookups in your filter const $duration = document.querySelector('#duration'); const $lowtemp = document.querySelector('#lowtemp'); const $hightemp = document.querySelector('#hightemp'); const $type = document.querySelector('#type'); const filterData = (params) => { return myTableData.filter((item) => { // if we have duration, check it if (params.duration && item.duration !== params.duration) { return false; } // if we have lowtemp, check it if (params.low_temp && item.low_temp !== params.low_temp) { return false; } // if we have hightemp, check it if (params.high_temp && item.high_temp !== params.high_temp) { return false; } // if we have type, check it if (params.type && item.type.toLowerCase() !== params.type) { return false; } // include this item return true; }); } document.querySelector('#filter').addEventListener('click', (e) => { // build up the params to filter by const params = {}; if ($duration.value) { // parse to int params.duration = parseInt($duration.value); } if ($lowtemp.value) { // parse to float params.low_temp = parseFloat($lowtemp.value); } if ($hightemp.value) { // parse to float params.high_temp = parseFloat($hightemp.value); } if ($type.value) { // convert to lowercase for comparison params.type = $type.value.toLowerCase(); } console.info(filterData(params).length); }); // few tests below let params = {}; console.info(filterData(params).length === 3); params = { duration: 246 }; console.info(filterData(params).length === 1); params = { duration: 247 }; console.info(filterData(params).length === 2); params = { duration: 247, low_temp: 373.0 }; console.info(filterData(params).length === 1); params = { low_temp: 374.0, high_temp: 388.0 }; console.info(filterData(params).length === 1); params = { type: 'lb', }; console.info(filterData(params).length === 2); params = { high_temp: 388.0, }; console.info(filterData(params).length === 3); });
Quel comportement souhaitez-vous si le champ de données de table n'est pas défini? Il sera exclu des résultats filtrés en tant qu'entrée "non correspondante"?
Oui! Exactement. maintenant, si une propriété n'est pas définie, le tableau entier retourne simplement vide. Je voudrais que la propriété indéfinie soit exclue du filtre.
qu'est-ce que
$ w
dans l'exemple?C'est l'élément d'entrée utilisateur. Similaire à document.getelementbyid