Filter object array from a Javascript search string

Asked

Viewed 84 times

3

I have an array of objects where sometimes a property can come null.

I need to apply a filter to this array to capture objects that have the field and functionality that are passed by a string in a directive on my front-end.

The string is passed as follows: campo#funcionalidade, but if the field is null, the string will be #funcionalidade.

I am unable to make the filter correctly so that the object is returned when the field is null or the string field der match.

Below is an example of the code:

const funcionalidades = [
  {
    "campo": null,
    "funcionalidadeNome":"configuracoes.cadastrocliente",
    "descricao":"Aqui é preenchido os dados básicos do cliente"
  },
  {
    "campo":"cnpj",
    "funcionalidadeNome":"configuracoes.cadastrocliente",
    "descricao":"CNPJ do cliente"
  },
  {
    "campo":"codigo",
    "funcionalidadeNome":"configuracoes.cadastrocliente",
    "descricao":"Código do cliente"
  },
  {
    "campo":"nome",
    "funcionalidadeNome":"configuracoes.cadastrocliente",
    "descricao":"Nome Fanstasia"
  },
  {
    "campo":"razaosocial",
    "funcionalidadeNome":"configuracoes.cadastrocliente",
    "descricao":"Razão Social"
  }
];

const aaa = (arr, teste) => {
  const [ campo, funcionalidade] = teste.split('#')
  console.log(`CAMPO: ${campo}, FUNCIONALIDADE: ${funcionalidade}`)
  
  return arr
    .filter(item => item.funcionalidadeNome === funcionalidade)
    .find(item => item.campo === campo)
}

console.log(aaa(funcionalidades, 'codigo#configuracoes.cadastrocliente'));
console.log(aaa(funcionalidades, 'cnpj#configuracoes.cadastrocliente'));
console.log(aaa(funcionalidades, '#configuracoes.cadastrocliente'));

Fiddle

2 answers

4

You need to consider at find() that the field value can be undefined, for in the split() the first index of the array is undefined for the field follows example with its modified code:

const funcionalidades = [
    {
    "campo": null,
    "funcionalidadeNome":"configuracoes.cadastrocliente",
    "descricao":"Aqui é preenchido os dados básicos do cliente"
  },
  {
    "campo":"cnpj",
    "funcionalidadeNome":"configuracoes.cadastrocliente",
    "descricao":"CNPJ do cliente"
  },
  {
    "campo":"codigo",
    "funcionalidadeNome":"configuracoes.cadastrocliente",
    "descricao":"Código do cliente"
  },
  {
    "campo":"nome",
    "funcionalidadeNome":"configuracoes.cadastrocliente",
    "descricao":"Nome Fanstasia"
  },
  {
    "campo":"razaosocial",
    "funcionalidadeNome":"configuracoes.cadastrocliente",
    "descricao":"Razão Social"
  }
];

const aaa = (arr, teste) => {
    const [ campo, funcionalidade] = teste.split('#');
  console.log(`CAMPO: ${campo}, FUNCIONALIDADE: ${funcionalidade}`)
  
    return arr
    .filter(item => item.funcionalidadeNome === funcionalidade)
    .find(item => item.campo === (!campo ? null : campo))
}

console.log(aaa(funcionalidades, 'codigo#configuracoes.cadastrocliente'));
console.log(aaa(funcionalidades, 'cnpj#configuracoes.cadastrocliente'));
console.log(aaa(funcionalidades, '#configuracoes.cadastrocliente'));

  • undefined is different from null javascript

3


Note that when the string is in a pattern like foo#bar and you divide it by the character #, returns an array as:

['foo', 'bar']

But when the string is in a pattern like #bar and you divide it by the character #, returns an array as:

['', 'bar']

So it is assumed that when the first element of the array is an empty string, the property campo of the object to be filtered should be null.

Applying this to the logic of filtering, you have something like this:

function filtrarArray(arr, stringDeFiltragem) {
  let [campo, funcionalidade] = stringDeFiltragem.split('#');
  if (campo === '') {
    campo = null;
  }

  return arr
    .filter((item) => item.funcionalidadeNome === funcionalidade)
    .find((item) => item.campo === campo);
}

const funcionalidades = [
  {
    campo: null,
    funcionalidadeNome: 'configuracoes.cadastrocliente',
    descricao: 'Aqui é preenchido os dados básicos do cliente'
  },
  {
    campo: 'cnpj',
    funcionalidadeNome: 'configuracoes.cadastrocliente',
    descricao: 'CNPJ do cliente'
  },
  {
    campo: 'codigo',
    funcionalidadeNome: 'configuracoes.cadastrocliente',
    descricao: 'Código do cliente'
  },
  {
    campo: 'nome',
    funcionalidadeNome: 'configuracoes.cadastrocliente',
    descricao: 'Nome Fanstasia'
  },
  {
    campo: 'razaosocial',
    funcionalidadeNome: 'configuracoes.cadastrocliente',
    descricao: 'Razão Social'
  }
];

console.log(filtrarArray(funcionalidades, 'codigo#configuracoes.cadastrocliente'));
console.log(filtrarArray(funcionalidades, 'cnpj#configuracoes.cadastrocliente'));
console.log(filtrarArray(funcionalidades, '#configuracoes.cadastrocliente'));

But note that the use of filter it is not necessary in this case, since one can do all the "logic of selection" direct in the find. Behold:

function filtrarArray(arr, stringDeFiltragem) {
  let [campo, funcionalidade] = stringDeFiltragem.split('#');
  if (campo === '') {
    campo = null;
  }

  return arr.find((item) =>
    item.funcionalidadeNome === funcionalidade &&
    item.campo === campo
  );
}

In this case, it is sufficient to use the logical operator AND (&&) to perform both conditions at the same time in the predicate passed to the Array.prototype.find. The result is exactly the same, but the advantage is that you don’t need to scan the array twice.


And of course, if the if is "too verbose", be cool and use the logical allocation operator ||=, introduced in a recent edition of Ecmascript. It would look like this:

function filtrarArray(arr, stringDeFiltragem) {
  let [campo, funcionalidade] = stringDeFiltragem.split('#');
  campo ||= null;

  return arr.find((item) =>
    item.funcionalidadeNome === funcionalidade &&
    item.campo === campo
  );
}
  • 1

    +1 could simplify making a campo = campo || null;, nay?

  • Yes! : ) But I preferred to use if to be less "complicated". Some people may not know how this operator works. Anyway, @Cmtecardeal, leave your comment to show this possibility to future readers, thank you!

  • 1

    Ah, @Cmtecardeal, even cooler would be using the ||=, hehe! D

  • 1

    Yes, I can, to help the future Clean Coders Masters :). That operator there once tied a knot in my head... XD. Deserves an edition this answer, puts the most complex operators for the Masters to use and impress...

  • 1

    @Cmtecardeal can really confuse using that operator so I used ternary operator in my reply, but this answer still improved the code, very good

  • 1

    @Cmtecardeal Remembering that not always the use of || will give the same result as if: https://ideone.com/kL0eKN (in the case of the question, I think so, because the split returns an array of strings, but depending on the case, it may give difference)

Show 1 more comment

Browser other questions tagged

You are not signed in. Login or sign up in order to post.