Search code examples
javascriptarraysjsonlistlodash

Filter deep nested array by list of rules with JS/lodash


A have a deep structure of statement delivery forms. Each form has own formats and each formats has their own frequency.

 const forms = [
      {
        value: "1",
        label: 'Email',
        formats: [
          {
            value: '1',
            label: 'PDF',
            frequency: [
              {
                value: 'D',
                label: 'Daily',
              },
              {
                value: 'W',
                label: 'Weekly',
              },
            ],
          },
          {
            value: '2',
            label: 'XML',
            frequency: [
              {
                value: 'D',
                label: 'Daily',
              },
            ],
          },
        ],
      },
      {
        value: '2',
        label: 'Post',
        formats: [
          {
            value: '1',
            label: 'PDF',
            frequency: [
              {
                value: 'D',
                label: 'Daily',
              },
              {
                value: 'W',
                label: 'Weekly',
              },
            ],
          },
          {
            value: '2',
            label: 'XML',
            frequency: [
              {
                value: 'D',
                label: 'Daily',
              },
            ],
          },
        ],
      },
    ];

I also has another array which contains objects that represents restrictions/rules for the form structure. Now I need to somehow loop every option and compare it with these restrictions. If that option will have same values (form, format and frequency) as one of the restriction objects, that specific option will be removed from the structure or it will stay there based on hide value. How can I achieve it or what strategy should I use please?

const restrictions = [
  {form: '1', format: '1', frequency: 'D', hide: false},
  {form: '1', format: '2', frequency: 'W', hide: true},
  {form: '2', format: '1', frequency: 'D', hide: true},
  {form: '2', format: '2', frequency: 'W', hide: false},
]

Solution

  • You can use destructuring assignments to make the code compact:

    const forms = [{"value":"1","label":"Email","formats":[{"value":"1","label":"PDF","frequency":[{"value":"D","label":"Daily"},{"value":"W","label":"Weekly"}]},{"value":"2","label":"XML","frequency":[{"value":"D","label":"Daily"}]}]},{"value":"2","label":"Post","formats":[{"value":"1","label":"PDF","frequency":[{"value":"D","label":"Daily"},{"value":"W","label":"Weekly"}]},{"value":"2","label":"XML","frequency":[{"value":"D","label":"Daily"}]}]}]
    
    const restrictions = [
      {form: '1', format: '1', frequency: 'D', hide: false},
      {form: '1', format: '2', frequency: 'W', hide: true},
      {form: '2', format: '1', frequency: 'D', hide: true},
      {form: '2', format: '2', frequency: 'W', hide: false},
    ]
    
    filteredForms = forms.map(({value: x, label, formats}) =>
      ({value: x, label, formats: formats.map(({value: y, label, frequency}) =>
          ({value: y, label, frequency: frequency.filter(({value: z}) =>
              restrictions.some(({form: xx, format: yy, frequency: zz, hide}) =>
                !hide && x===xx && y===yy && z===zz
    ))}))}))
    
    console.log(filteredForms)