1

I'm writing a JSON array filter function based on multiple criteria.
The filter depends on two arrays: 1. The first one contains values that have to be part of searched JSON, and 2. the second contains values that are optional.

I mean to return only the array entries that contain ALL the values from the obligatory array and at least one item from the optional array.

Here's my attempt:

const searchKeys = ['varWord', 'varTrans', 'varSpec'],
  obligatory = ['trip', 'pret'],
  optional = ['greet', 'lco', 'toto', 'bene'];

function filterByUpdate(obligatory, optional, file) {
  return _.filter(file, item => {
    return _.some(optional, opt => {
      return _.every(obligatory, oblg => {
        return _.some(item, value => {
          return _.some(searchKeys, n => item[n].toLowerCase().includes(oblg.toLowerCase())) &&
            searchKeys.some(n => item[n].toLowerCase().includes(opt.toLowerCase()))
        })
      });
    });
  });
}

The code above should only preserve the first entry from the following data array:

[{
  "varSpec": "trip",
  "varTrans": "pret",
  "varWord": "greet",
  "stringPol": "group",
  "stringDva": "groupGend",
  "stringGit": "/tax",
}, {
  "varSpec": "trip",
  "varTrans": "pret",
  "varWord": "friend",
  "stringPol": "N",
  "stringDva": "N",
  "stringGit": "N",
}, {
  "varSpec": "group1",
  "varTrans": "grp1",
  "varWord": "ageGroup1",
  "stringPol": "N",
  "stringDva": "N",
  "stringGit": "N",
}]
4
  • searchKeys is an array of JSON Keys, that contain searched values. Commented Sep 23, 2018 at 16:27
  • Seems to be working fine. What output you want. It is returning varSpec: "trip" varTrans: "pret" varWord: "greet" stringPol: "group" stringDva: "groupGend" stringGit: "/tax" Commented Sep 23, 2018 at 16:28
  • 1
    codesandbox.io/s/k578p37j03 Commented Sep 23, 2018 at 16:34
  • ooh yes you are right! thank you for your time, my problem was in different part of my code. Commented Sep 23, 2018 at 17:57

1 Answer 1

2

You could go for this pretty simple algorithm:

const { flow, intersection, pick } = require('lodash/fp');

data.filter(
  flow(
    pick(searchKeys),
    entry => intersection(Object.values(entry)),
    intersectWith => intersectWith(obligatory).length === obligatory.length &&
                     intersectWith(optional).length >= 1
  )
);

It basically boils down to checking for the intersection between, on the first hand, the relevant values (identified by searchKeys) in each entry of your dataset (data), and on the other:

  1. the obligatory array of values: the intersection must be of obligatory.length length.
    i.e.: it contains all the items from the obligatory collection
  2. the optional array of values: the intersection array's length must be >= 1.
    i.e.: it contains at least 1 item from the optional collection

Here's a link to a working repl.

Sign up to request clarification or add additional context in comments.

1 Comment

thank you man, really appreciate your help and provided example. Gonna try it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.