Q:

Recursively filter array of objects with different properties

I have a object with others arrays. I need to filter when in the main array match RazaoSocial:"AAS" or Produtos:[{Descricao:"AAS"}]
That's my code:
var input = [
  {
    RazaoSocial: 'AAS',
    Produtos: [
    { DescricaoProduto: 'XXX', id:12, other:"other text" },
      { DescricaoProduto: 'YYY', id:12, other:"other text" }
    ]
  },
  {
    RazaoSocial: 'I found you',
    Produtos: [
      { DescricaoProduto: 'AAS', id:12, other:"other text" },
      { DescricaoProduto: 'Miss8', id:12, other:"other text" },
      { DescricaoProduto: 'Miss8', id:12, other:"other text" },
      { DescricaoProduto: 'Miss8', id:99, other:"other text" }      
    ]
  },
  {
    RazaoSocial: 'bla',
    Produtos: [
        { DescricaoProduto: 'AB', id:12, other:"other text" },
        { DescricaoProduto: 'CD', id:12, other:"other text" },
    ]
  },  
];

var res = input.filter(function f(o) {
    if (o.RazaoSocial.includes("AAS")) return true
    if (o.Produtos.DescricaoProduto) {
        console.log(o.Produtos);
        return (o.Produtos = o.Produtos.filter(f)).length
    }
})
 console.log(JSON.stringify(res, null, 2));

//result
[
  {
    "RazaoSocial": "AAS",
    "Produtos": [
      {
        "DescricaoProduto": "XXX",
        "id": 12,
        "other": "other text"
      },
      {
        "DescricaoProduto": "YYYAAS",
        "id": 12,
        "other": "other text"
      }
    ]
  }
]

Why the object with "i found you" it's not returned ? I was expeting
[
        {
            RazaoSocial: 'AAS',
            Produtos: [
                { DescricaoProduto: 'XXX', id: 12, other: "other text" },
                { DescricaoProduto: 'YYY', id: 12, other: "other text" }
            ]
        },
        {
            RazaoSocial: 'I found you',
            Produtos: [
                { DescricaoProduto: 'AAS', id: 12, other: "other text" },
                { DescricaoProduto: 'Miss8', id: 12, other: "other text" },
                { DescricaoProduto: 'Miss8', id: 12, other: "other text" },
                { DescricaoProduto: 'Miss8', id: 99, other: "other text" }
            ]
        }
    ]

I tried the examples in, but with no success.
Recursively filter array of objects
What I'm doing wrong ?
thanks for the help.

A:

The main problem with the original attempt was the if (o.Produtos.DescricaoProduto) {
o.Produtos is an array so you cannot access o.Produtos.DescricaoProduto without first getting an index.
So since o.Produtos is an array we can go ahead and filter it like we did the original input.
I've added both a recursive and non-recursive approach you could compare.
The recursive solution is entirely generic and can find any given value.

var input = [
  {
    RazaoSocial: 'AAS',
    Produtos: [
      { DescricaoProduto: 'XXX', id:12, other:"other text" },
      { DescricaoProduto: 'YYY', id:12, other:"other text" }
    ]
  },
  {
    RazaoSocial: 'I found you',
    Produtos: [
      { DescricaoProduto: 'AAS', id:12, other:"other text" },
      { DescricaoProduto: 'Miss8', id:12, other:"other text" },
      { DescricaoProduto: 'Miss8', id:12, other:"other text" },
      { DescricaoProduto: 'Miss8', id:99, other:"other text" }      
    ]
  },
  {
    RazaoSocial: 'bla',
    Produtos: [
        { DescricaoProduto: 'AB', id:12, other:"other text" },
        { DescricaoProduto: 'CD', id:12, other:"other text" },
    ]
  },  
];

var useRecursive = true, 
    res;
if (useRecursive) {
  var findValue = function (str) {
      return function(o) {
          return Object.values(o).filter(function (value) {
              if (Array.isArray(value)) {
                  return value.filter(findValue(str)).length > 0
              } else {
                  return value.toString().includes(str)
              }
          }).length > 0;
      };
  };
  res = input.filter(findValue("AAS"))

} else {
  res = input.filter(function f(o) {
    if (o.RazaoSocial.includes("AAS")) return true
    if (o.Produtos.length) {
        return o.Produtos.filter(function(o1) {
          return o1.DescricaoProduto.includes("AAS");
        }).length;
    }
  })
}
console.log(JSON.stringify(res, null, 2));

