Array.filter with several conditional

I have an array of objects that I would like to filter and divide into groups according to the conditional. The problem arises because I have more than one conditional expression, and I would like the array to be divided into several arrays. The first array corresponds to the first conditional, the second array corresponds to the second conditional, ... and the last array containing all objects that do not match any conditional expression.

The first solution that came up with this problem was in the form of several .filter functions ...

var array = [{
  name: 'X',
  age: 18
}, {
  name: 'Y',
  age: 18
}, {
  name: 'Z',
  age: 20
}, {
  name: 'M',
  age: 20
}, {
  name: 'W',
  age: 5
}, {
  name: 'W',
  age: 10
}];
//objects with age 18
var matchedConditional1 = array.filter(function(x){
  return x.age === 18;
});
//objects with age 20
var matchedConditional2 = array.filter(function(x){
  return x.age === 20;
});
//objects with neither age 18 or 20
var matchedNoConditional = array.filter(function(x){
  return (x.age !== 18 && x.age !== 20);
});

but it seemed redundant and not reused.

So, I changed the function on Brendan's answer and got this.

Array.prototype.group = function(f) {
  var matchedFirst = [],
      matchedSecond = [],
      unmatched = [],
      i = 0,
      l = this.length;
  for (; i < l; i++) {
    if (f.call(this, this[i], i)[0]) {
      matchedFirst.push(this[i]);
    } else if (f.call(this, this[i], i)[1]) {
      matchedSecond.push(this[i]);
    } else {
      unmatched.push(this[i]);
    }
  }
  return [matchedFirst, matchedSecond, unmatched];
};
var filteredArray = array.group(function(x){
  return [x.age === 18, x.age === 20];
});

3 . , , , , , .

, , , . , , , .

, , , - .

Ps. , , . . .map .reduce. .

: @slebetman, , .

+4
2

- :

Array.prototype.groups = function(...conditions) {
  return this.reduce(
    (groups, entry) => {
      let indices = [];

      conditions.forEach((cond, i) => {
        if (cond(entry)) indices.push(i);
      });

      if (indices.length === 0) groups[groups.length - 1].push(entry);
      else indices.forEach(i => groups[i].push(entry));

      return groups
    }, 
    Array.apply(null, { length: conditions.length + 1})
      .map(e => [])
  );
}

, , .

: array.groups(x => x.name === 'X', x => x.age === 18);

- .

+2

findIndex, , , :

function makeGrouper(...conditions) {

  return function(array) {
    // Make an array of empty arrays for each condition, plus one.
    var results = conditions.map(_ => []).concat([]);

    array.forEach(elt => {
      var condition = conditions.findIndex(condition => condition(elt));
      if (condition === -1) condition = conditions.length;
      results[condition].push(elt);
    });

    return results;
  };

}

, reduce:

function makeGrouper(...conditions) {

  return function(array) {
    return array.reduce((results, elt) => {
      var condition = conditions.findIndex(condition => condition(elt));
      if (condition === -1) condition = conditions.length;
      results[condition].push(elt);
      return results;
    }, conditions.map(_ => []).concat([])));  
  };

}

:

const grouper = makeGrouper(
  elt => elt.age === 18,
  elt => elt.age === 20
);

console.log(grouper(data));

, , , .

+2

Source: https://habr.com/ru/post/1648988/


All Articles