1

I'm aware of similar questions such as here but I can't figure out what should be an easy problem. I'm trying to filter an object of objects for truthy values.

const obj = {
  piano: {
    scales: { essential: 1 },
    chords: { essential: 1 },
    triads: { essential: 0 },
  },
  bass: { scales: { essential: 1 }, triads: { essential: 0 } },
};
function getEssential(state) {
  return Object.fromEntries(
    Object.entries(state).filter(([, val]) => val.essential)
  );
}

const resOne = Object.fromEntries(
  Object.entries(obj.piano).filter(([, val]) => val.essential)
);

const resTwo = Object.keys(obj).forEach((el) =>
  Object.entries(obj[el]).filter(([, val]) => val.essential)
);

const resThree = Object.keys(obj).forEach((el) => getEssential(el));

console.log(resOne);
console.log(resTwo);
console.log(resThree);

See that resOne gives desired output but for only one key (piano in this case). I know I can make an empty array and add the ones that pass the test but there must be a more efficient way.

How do I take an object, loop through all keys, apply the filter and return the same object minus the properties essential !== 1?

Current output:

{ scales: { essential: 1 }, chords: { essential: 1 } }
undefined
undefined

4 Answers 4

1

You need a nested approach for nested entries.

function getEssential(state) {
    return Object.fromEntries(Object
        .entries(state)
        .map(([k, v]) => [k, Object.fromEntries(Object.entries(v).filter(([, val]) => val.essential))])
    );
}

const obj = {
  piano: {
    scales: { essential: 1 },
    chords: { essential: 1 },
    triads: { essential: 0 },
  },
  bass: { scales: { essential: 1 }, triads: { essential: 0 } },
};

console.log(getEssential(obj));

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

Comments

1
  • Using Object.entries, you can get each sub object values and can get the filtered entries using Array.filter.
  • After that, using Object.fromEntries, you can regenerate the object from filtered entries

const obj = {
  piano: {
    scales: { essential: 1 },
    chords: { essential: 1 },
    triads: { essential: 0 },
  },
  bass: { scales: { essential: 1 }, triads: { essential: 0 } },
};

const getEssentials = (obj) => {
  const result = {};
  const keys = Object.keys(obj);
  keys.forEach(key => {
    var entries = Object.entries(obj[key]).filter(([subKey, subValue]) => subValue.essential);
    result[key] = Object.fromEntries(entries);
  });
  
  return result;
};

console.log(getEssentials(obj));

1 Comment

Thanks it works. As mentioned i'm aware pushing to arrays would work but was looking for an approach that uses map or reduce,
1

You could do this using recursive approach with a for...in loop and add property to result only if property essential: 1 is found on some level.

const obj = {
  piano: { scales: { essential: 1 }, chords: { essential: 1 }, triads: { essential: 0 } },
  bass: { scales: { essential: 1 }, triads: { essential: 0 } },
};

function filter(obj) {
  const result = {}

  for (let i in obj) {
    if (typeof obj[i] === 'object') {
      const val = filter(obj[i])

      if (val) {
        result[i] = val;
      }
    } else {
      if (i === 'essential' && obj[i] != 1) {
        return false
      } else {
        result[i] = obj[i]
      }
    }
  }

  return result;
}

console.log(filter(obj))

Comments

1

const obj = {
  piano: {
    scales: { essential: 1 },
    chords: { essential: 1 },
    triads: { essential: 0 },
  },
  bass: { scales: { essential: 1 }, triads: { essential: 0 } },
};

const filtered = Object.fromEntries(
  Object.entries(obj)
    .map(e => [e[0], Object.entries(e[1]).reduce((acc, [key, val]) => {
      if (!!val.essential) acc = {...acc, [key]: val}
      return acc
    }, {})]
  )
)

console.info(filtered)

2 Comments

I downvoted this as it's not correct. You're using obj.piano whereas it has to be key agnostic. See the answer from Nina Scholz. What you've provided does the same thing as my code already.
@noblerthanoedipus now I understand what you want, easily fixable by iterating through root properties too. Check. For me, using map and reduce is a bit more readable.

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.