Home:ALL Converter>Javascript array filter with conditional output / apply

Javascript array filter with conditional output / apply

Ask Time:2020-05-06T18:11:15         Author:Matthias

Json Formatter

I'm wondering, if there is a way to filter an array or stream and apply a function A to all matches and a function B to all non-matches in JavaScript. Here is some example code that explains it a bit more:

  // initial data
  var names = ['Matthias', 'Maria', 'Bob', 'Anton'];
  var namesWithM;
  var namesWithoutM;

  // gets only names starting with M, but not the others at the same time
  namesWithM = names.filter(name => name.startsWith('M'))

  // conditional lambda version
  namesWithM = [];
  namesWithoutM = [];
  names.forEach(name => name.startsWith('M') ? namesWithM.push(name) : namesWithoutM.push(name));


  // conditional classical version
  namesWithM = [];
  namesWithoutM = [];
  names.forEach(function(name) {
    if (name.startsWith('M'))
      namesWithM.push(name)
    else
      namesWithoutM.push(name);
  });

The very first version handles just the matches but uses filter and not forEach. Is there any way to use filter and apply a function for matches and non-matches at once? Something like this pseudo code:

names.filter(name.startsWith('M')).apply(namesWithM::push).or(namesWithoutM::push);

Author:Matthias,eproduced under the CC 4.0 BY-SA copyright license with a link to the original source and this disclaimer.
Link to original article:https://stackoverflow.com/questions/61632571/javascript-array-filter-with-conditional-output-apply
Józef Podlecki :

I would use reduce to group data into 2 mentioned cases. I don't see any reason to use filter here\n\n\r\n\r\nlet names = ['Matthias', 'Maria', 'Bob', 'Anton'];\r\n\r\nlet [namesWithM, namesWithoutM] = names.reduce((acc, name) => {\r\n\r\n if (name.startsWith('M')) {\r\n acc[0] = [...(acc[0] || []), name]\r\n return acc;\r\n }\r\n\r\n acc[1] = [...(acc[1] || []), name]\r\n return acc;\r\n\r\n}, [])\r\n\r\n// simpler version\r\nconsole.log(namesWithM, namesWithoutM);\r\n\r\nlet [namesWithM1, namesWithoutM1] = names.reduce((acc, name) => {\r\n const index = Number(!name.startsWith('M'));\r\n acc[index] = [...(acc[index] || []), name];\r\n return acc;\r\n}, [])\r\n\r\nconsole.log(namesWithM1, namesWithoutM1);",
2020-05-06T10:17:48
brk :

filter returns an array. So you can use this array to fill with name which either starts with M or not.\n\nIn the below example the filter is filling the array with name starts with M. In filter callback the name not starting with M are filled in another array\n\n\r\n\r\n// initial data\r\nvar names = ['Matthias', 'Maria', 'Bob', 'Anton'];\r\nvar namesWithM;\r\nvar namesWithoutM = [];\r\n\r\nnamesWithM = names.filter((name) => {\r\n if (!name.startsWith('M')) {\r\n namesWithoutM.push(name)\r\n }\r\n return name.startsWith('M');\r\n});\r\n\r\nconsole.log(namesWithM, namesWithoutM);",
2020-05-06T10:18:01
yy