0

I'm a newbie in Javascript and I'm trying to understand the destructuring approach also with object literals. So what I'm trying to do is to create a function which has two types of arguments: 1. It's a JSON data file which I want to iterate. 2. An object literal with a random value assigned. So I'm trying to iterate with this object value passed as a parameter and filter with the data from the JSON file with an if statement inside the array of objects iterator. And add to arr all the object which match. Thanks everyone in advance.

Array of objects:

[
  { "id": 44, "hours": 100,"finished": false },
  { "id": 22, "hours": 80,"finished": false },
  { "id": 65, "hours": 34,"finished": false },
  { "id": 1098, "hours": 21,"finished": true  },
  { "id": 2, "hours": 67,"finished": false },
  { "id": 765, "hours": 32,"finished": false },
  { "id": 223, "hours": 555,"finished": false },
  { "id": 986, "hours": 2,"finished": false }
]

main.js

const data = require('./example.json')

function dataFilter (items, {id: _id, hours: _hours, finished: _finished}) {

for (let i = 0; i < items.length; i++) {
    let arr = [];
    if (items[i].id === _id) {
        arr.push(items[i])
    }
    else if (items[i].hours >= _hours){
        arr.push(items[i])
    }
    else if (items[i].finished === finished){
        arr.push(items[i])
    }
    return arr;
  }
}

console.log(dataFilter(data,{ id: 65 }));
console.log(dataFilter(data,{ hours: 30 }));
Kaiser91
  • 333
  • 6
  • 17

2 Answers2

0

You don't need destructuring, what you need is array filter.

You also forgot to set a default {} so you can access undefined keys:

https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Objets_globaux/Array/filter

const data = [
  { "id": 44, "hours": 100,"finished": false },
  { "id": 22, "hours": 80,"finished": false },
  { "id": 65, "hours": 34,"finished": false },
  { "id": 1098, "hours": 21,"finished": true  },
  { "id": 2, "hours": 67,"finished": false },
  { "id": 765, "hours": 32,"finished": false },
  { "id": 223, "hours": 555,"finished": false },
  { "id": 986, "hours": 2,"finished": false },
  { "id": 1986, "hours": 30,"finished": false },
];

function dataFilter (items, {id: _id, hours: _hours, finished: _finished} = {}) {
  return items.filter((item) => item.id === _id || item.hours >= _hours || item.finished === _finished);
}

document.getElementById('results').innerHTML = `
<pre>
ID: 65
${JSON.stringify(dataFilter(data,{ id: 65 }), null, 2)}
  
HOURS: 30
${JSON.stringify(dataFilter(data,{ hours: 30 }), null, 2)}
</pre>
`
<div id="results"></div>

Approach with multiple filters

It is also possible to use more than one filter at once:

const data = [
  { "id": 44, "hours": 100,"finished": false },
  { "id": 22, "hours": 80,"finished": false },
  { "id": 65, "hours": 34,"finished": false },
  { "id": 1098, "hours": 21,"finished": true  },
  { "id": 2, "hours": 67,"finished": false },
  { "id": 765, "hours": 32,"finished": false },
  { "id": 223, "hours": 555,"finished": false },
  { "id": 986, "hours": 2,"finished": false },
  { "id": 1986, "hours": 30,"finished": false },
];

function dataFilter (items, filters = {}) {
  // this will create a list of function on the fly for every `filters` you pass.
  const fnList = Object.keys(filters)
    .map((key) => (list) => list.filter((item) => item[key] === filters[key]));
    
  let res = [...items];
  while (cursor = fnList.shift()) {
    res = cursor(res);
  }
  return res;
}

document.getElementById('results').innerHTML = `
<pre>
ID: 44, HOURS: 100
${JSON.stringify(dataFilter(data,{ id: 44, hours: 100 }), null, 2)}
  
ID: 2, HOURS: 67
${JSON.stringify(dataFilter(data,{ id: 2 }), null, 2)}
</pre>
`
<div id="results"></div>

If you want to specify the operators used for the comparaison, use a fonction as explained here: Are Variable Operators Possible?

Dimitri Kopriwa
  • 13,139
  • 27
  • 98
  • 204
  • Thx, this approach looks cool, but I was trying to pass e.g 3 values as a parameter _{id: 45, hours: 10, finished: true}_ so the result will be just the objects which match with those parameters. – Kaiser91 Feb 23 '19 at 17:17
  • I have added an approach with multiple items. – Dimitri Kopriwa Feb 23 '19 at 18:12
0

Looks like you want to be able to filter the data by any combination of the three items in that object.

function filterFactory({id, hours, finished}) {
  return function filter(item) {
    let isGoodValue = false;
    if (id !== undefined && item.id === id) isGoodValue = true;

    // for the second and third checks we'll short-circuit if it already
    // passed an earlier check
    if (!isGoodValue && hours !== undefined && item.hours >= hours) isGoodValue = true;
    if (!isGoodValue && finished !== undefined && item.finished === finished) isGoodValue = true;
    return isGoodValue;
  };
}

data.filter(filterFactory({id: 2})); 

Note that we're using the native filter method on arrays. filterFactory is a factory that makes callbacks to pass to filter based on one or more of the three factors you're filtering on.

Jared Smith
  • 19,721
  • 5
  • 45
  • 83