2
\$\begingroup\$

deepFilter function uses a predicate to filter properties which may be nested deeply in the given value (object or array). It returns filtered object or array.

The code works for most inputs (arbitrary levels of nesting and input without cyclic references). I'm more interested in comments on my approach to FP than correctness of the code. Though I wouldn't mind if you point a mistake.

const and = (f1, f2) => v => f1(v) && f2(v);

const or = (f1, f2) => v => f1(v) || f2(v);

const isArray = v => Array.isArray(v);

const isObject = v => typeof v === 'object' && v !== null;

const hasProps = v => Object.keys(v).length > 0;

const selector = (predicate, v1, v2) => v => (predicate(v) ? v1 : v2);

const isObjectOrArray = or(isArray, isObject);

const hasValue = and(isObjectOrArray, hasProps);

const initial = selector(isArray, [], {});

function deepFilter(value, predicate) {
  if (isObjectOrArray(value)) {
    return Object.keys(value).reduce((filtered, key) => {
      if (predicate(key)) {
        return { ...filtered, [key]: value[key] };
      }
      const v = deepFilter(value[key], predicate);
      return hasValue(v) ? { ...filtered, [key]: v } : filtered;
    }, initial(value));
  }
  return value;
}
\$\endgroup\$
  • 1
    \$\begingroup\$ Problem with your code is that many JavaScript objects are cyclic, and you do not check. eg Try and run deepFilter(window, v => v === "somePropertyName"); \$\endgroup\$ – Blindman67 Feb 10 '18 at 20:16
  • \$\begingroup\$ Good catch. I need to see how I can work around those situations. Thanks. \$\endgroup\$ – Nishant Shreshth Feb 11 '18 at 18:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.