Javascript фильтр массива с условным выводом / применением - PullRequest
1 голос
/ 06 мая 2020

Мне интересно, есть ли способ отфильтровать массив или поток и применить функцию A ко всем совпадениям и функцию B ко всем несовпадениям в JavaScript. Вот пример кода, который объясняет это немного подробнее:

  // 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);
  });

Самая первая версия обрабатывает только совпадения, но использует filter, а не forEach. Есть ли способ использовать filter и применить функцию для совпадений и несовпадений одновременно? Что-то вроде этого псевдокода:

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

Ответы [ 3 ]

2 голосов
/ 06 мая 2020

фильтр возвращает массив. Таким образом, вы можете использовать этот массив для заполнения name, который либо начинается с M, либо нет.

В приведенном ниже примере фильтр заполняет массив с именем, начинающимся с M. В обратном вызове filter имя, не начинающееся с M, заполняется другим массивом

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

namesWithM = names.filter((name) => {
  if (!name.startsWith('M')) {
    namesWithoutM.push(name)
  }
  return name.startsWith('M');
});

console.log(namesWithM, namesWithoutM);
1 голос
/ 06 мая 2020

Я бы использовал reduce, чтобы сгруппировать данные в 2 упомянутых случая. Не вижу смысла использовать здесь filter

let names = ['Matthias', 'Maria', 'Bob', 'Anton'];

let [namesWithM, namesWithoutM] = names.reduce((acc, name) => {

  if (name.startsWith('M')) {
    acc[0] = [...(acc[0] || []), name]
    return acc;
  }

  acc[1] = [...(acc[1] || []), name]
  return acc;

}, [])

// simpler version
console.log(namesWithM, namesWithoutM);

let [namesWithM1, namesWithoutM1] = names.reduce((acc, name) => {
    const index = Number(!name.startsWith('M'));
    acc[index] = [...(acc[index] || []), name];
    return acc;
}, [])

console.log(namesWithM1, namesWithoutM1);
0 голосов
/ 06 мая 2020
const names = ['Matthias', 'Maria', 'Bob', 'Anton'];
function A(item){
  console.log('filtered');
  console.log(item);
}
function B(item){
  console.log('not-ffiltered');
  console.log(item);
}
const filteredNames = names.filter(name => {
  const isValid = name.startsWith('M')
  if(isValid)
    A(name)
  else
    B(name)
  return isValid;
})
...