Filtering on an array of object literal properties and their nested array values This is a function which filters on multiple object properties and their corresponding arrays. 


I need to match all properties to a pattern and have an array as their property value. 
Properties that match that pattern and contain an array get filtered on whether they contain string values.
The values can be in any one of the arrays related to that object. 
All objects which have met the criteria and contain the appropriate strings irrespective of the property array they are contained in. With the exception being that all values are in the same object.
The object containing all string values do not get filtered out. 




If I match all object properties containing 'ev_' and those properties contain arrays whose values include 'value75' and '12+'   

This should be the resulting output 

{
  "data": {
    "id": 3,
    "date": "2019-02-03",
    "ev_filter_1": [
      "art",
      "foodie"
    ],
    "ev_filter_2": [
      "value1",
      "value75"
    ],
    "ev_filter_3": [
      "value1",
      "value2"
    ],
    "ev_filter_4": [
      "all",
      "12+"
    ]
  }
}


From this array of objects

const posts = [{
    data: {
      id: 1,
      date: "2019-02-03",
      ev_filter_1: ["art", "foodie"],
      ev_filter_2: ["value1", "value2"],
      ev_filter_3: ["value1", "value2"],
      ev_filter_4: ["all", "12+"]
    }
  },
  {
    data: {
      id: 2,
      date: "",
      ev_filter_1: ["arti", "foodie"],
      ev_filter_2: ["value1", "value2"],
      ev_filter_3: ["value1", "value2"],
      ev_filter_4: ["all", "19+"]
    }
  },
  {
    data: {
      id: 3,
      date: "2019-02-03",
      ev_filter_1: ["art", "foodie"],
      ev_filter_2: ["value1", "value75"],
      ev_filter_3: ["value1", "value2"],
      ev_filter_4: ["all", "12+"]
    }
  }
];




This example is currently working but it is ugly and rigid. The "some" is just used for iteration, which I painfully coerced to return true. There is also a nested if statement (horrid). 



const posts = [{
    data: {
      id: 1,
      date: "2019-02-03",
      ev_filter_1: ["art", "foodie"],
      ev_filter_2: ["value1", "value2"],
      ev_filter_3: ["value1", "value2"],
      ev_filter_4: ["all", "12+"]
    }
  },
  {
    data: {
      id: 2,
      date: "",
      ev_filter_1: ["arti", "foodie"],
      ev_filter_2: ["value1", "value2"],
      ev_filter_3: ["value1", "value2"],
      ev_filter_4: ["all", "19+"]
    }
  },
  {
    data: {
      id: 3,
      date: "2019-02-03",
      ev_filter_1: ["art", "foodie"],
      ev_filter_2: ["value1", "value75"],
      ev_filter_3: ["value1", "value2"],
      ev_filter_4: ["all", "12+"]
    }
  }
];

function sift(arrObjLit, pattern, argOne, argTwo) {
  return arrObjLit.filter(function(x, y) {
    return (result = Object.entries(x).some((q, i) =&gt; {
      for (let [key, v] of Object.entries(q[1])) {
        if (key.startsWith(pattern) &amp;&amp; Array.isArray(v) &amp;&amp; v.includes(argOne)) {
          for (let an of Object.values([x.data][0])) {
            if (Array.isArray(an) &amp;&amp; an.includes(argTwo)) {
              return true;
            }
          }
        }
      }
    }))
  })
}

console.log(...sift(posts, "ev_", "value75", "12+"));
First, and I can't emphasize this enough, use meaningful variable names. What is argOne? argTwo? The same goes for all of your single letter variable names. They make it harder to look at your code and figure out what's going on.

To help you see where the code you provided might be difficult to understand, I've copied it and commented what came to mind when reading each line, hopefully this can help with writing code that self-documents.

// It looks like this will filter arrObjLit based on pattern.
// But what is argOne, argTwo? Do I need both? What if I include argThree?
function sift(arrObjLit, pattern, argOne, argTwo) {
  // Filtering as expected, but why is the index y needed? 
  return arrObjLit.filter(function(x, y) {
    // Where did result come from? Right now it declares a global variable.
    // What is q? Is the index of it, i, needed?
    // Does this need to be wrapped in parenthesis?
    // The above line used function, here there's an arrow function. Why?
    return (result = Object.entries(x).some((q, i) =&gt; {
      // Okay, q[1] is the value, but q[0] isn't used, maybe 
      // Object.values() should be used above?
      // What happens if q isn't an object?
      for (let [key, v] of Object.entries(q[1])) {
        // This is clear, but what is special about argOne? 
        // Why not check argTwo here too?
        if (key.startsWith(pattern) &amp;&amp; Array.isArray(v) &amp;&amp; v.includes(argOne)) {
          // Why is [x.data][0] used instead of just x.data?
          // x.data == q[1]? What happens if q[1] != x.data?
          for (let an of Object.values([x.data][0])) {
            // Why don't we check that the key for the an array starts 
            // with key like we did for argOne?
            if (Array.isArray(an) &amp;&amp; an.includes(argTwo)) {
              return true;
            }
          }
        }
      }
    }))
  })
}


In chat, you mentioned that ideally, every array contained within the object should be searched, if it matches the pattern. With this in mind, here is how I would solve your problem. (It might be a good idea to rename pattern to prefix, with pattern I would expect that I can pass in a regular expression)

function sift(entries, pattern, ...filters) {
  return entries.filter(entry =&gt; {
    // Copy the filters array into a set
    let toMatch = new Set(filters);

    let searchForMatches = root =&gt; {
      for (let [key, value] of Object.entries(root)) {
        if (Array.isArray(value) &amp;&amp; key.startsWith(pattern)) {
          // The key for the array matches the pattern, so remove all of these
          // items from the required items to match, if they are found
          value.forEach(item =&gt; toMatch.delete(item));
        } else if (typeof value == 'object' &amp;&amp; value) {
          // This item isn't null, and is an object.
          // It may contain an array, recurse
          searchForMatches(value);
        }
      }
    };

    searchForMatches(entry);

    // If the set is empty, all matches were found
    // and this object should be included in the result.
    return toMatch.size == 0;
  });
}