1

I have a JavaScript object with several properties:

{
  banking: {
    account_number: null,
    account_type: null,
    bank_name: null,
    debit_day: null
  },
  fitment: {
    date: null,
    terms: null
  },
  personal_info: {
    email: null,
    IDNumber: null,
    mobile: null,
    name: null,
    residential_address: null,
    surname: null,
    title: null,
    work_address: null,
    work_tel: null
  },
  vehicle: {
    brand: null,
    colour: null,
    model: null,
    registration: null,
    vin: null,
    year: null
  }
}

All top level properties and nested properties has default value of null.

I'm trying to figure out a way to categorize the properties into three groups, namely:

empty, partial and complete.

"empty" being a case that all values within a section are set as null.

"partial" being that some values within a section have been set (not all null)

"complete" being that no values within a section are set to null. All have values.

My first attempt was with utilizing the Underscore library with _.some(), however I can't seem to wrap my head around catering for all group scenarios.

Some help and guidance will be much appreciated.

Thanks!

1
  • by categorize what do you mean? do you just want a separate array/object that returns each section category or you want to add a new key to each section where you save the category value? Commented Feb 22, 2023 at 17:22

2 Answers 2

1

You could check for every first, and then follow-up with some, or default to empty.

const main = () => {
  const sectionStatus = Object.fromEntries(
    Object.entries(sections).map(([section, data]) => [
      section,
      Object.entries(data).every(([id, value]) => value !== null)
        ? 'complete'
        : Object.entries(data).some(([id, value]) => value !== null)
          ? 'partial'
          : 'empty'
    ]));
  
  console.log(sectionStatus);
};

const sections = {
  banking: {
    account_number: '555',
    account_type: null,
    bank_name: null,
    debit_day: null
  },
  fitment: {
    date: new Date(),
    terms: 'foobar'
  },
  personal_info: {
    email: null,
    IDNumber: null,
    mobile: null,
    name: null,
    residential_address: null,
    surname: null,
    title: null,
    work_address: null,
    work_tel: null
  },
  vehicle: {
    brand: null,
    colour: null,
    model: null,
    registration: null,
    vin: null,
    year: null
  }
};

main();
.as-console-wrapper { top: 0; max-height: 100% !important; }

Output

{
  "banking": "partial",
  "fitment": "complete",
  "personal_info": "empty",
  "vehicle": "empty"
}

If you want to optimize this you can mark each field with a 1 (not null) or 0 (null) and reduce the values.

const main = () => {
  const sectionStatus = Object.fromEntries(
    Object.entries(sections).map(([section, data]) => { 
      const flags = Object.values(data).map((v) => v !== null ? 1 : 0);
      const state = flags.reduce((a, b) => a & b, 1) === 1 // or (a * b)
        ? 'complete'
        : flags.reduce((a, b) => a | b, 0) === 1 // or (a + b) > 0
          ? 'partial'
          : 'empty';
      return [section, state];
    }, []));
  
  console.log(sectionStatus);
};

const sections = {
  banking: {
    account_number: '555',
    account_type: null,
    bank_name: null,
    debit_day: null
  },
  fitment: {
    date: new Date(),
    terms: 'foobar'
  },
  personal_info: {
    email: null,
    IDNumber: null,
    mobile: null,
    name: null,
    residential_address: null,
    surname: null,
    title: null,
    work_address: null,
    work_tel: null
  },
  vehicle: {
    brand: null,
    colour: null,
    model: null,
    registration: null,
    vin: null,
    year: null
  }
};

main();
.as-console-wrapper { top: 0; max-height: 100% !important; }

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

1 Comment

Works exactly as intended. Thanks so much!
0

You can further decompose this problem by also using _.groupBy. First, a function just to determine the category of a single section:

function category(section) {
    return _.every(section, _.isNull) ? 'empty' :
           _.some(section, _.isNull) ? 'partial' : 'complete';
}

Then, combine this with _.groupBy to create an array of original objects for each category:

_.groupBy(sections, category)

Putting it all together:

var sections = {
  banking: {
    account_number: null,
    account_type: null,
    bank_name: null,
    debit_day: null
  },
  fitment: {
    date: null,
    terms: null
  },
  personal_info: {
    email: null,
    IDNumber: null,
    mobile: null,
    name: 'Jane Doe',
    residential_address: null,
    surname: null,
    title: null,
    work_address: null,
    work_tel: null
  },
  vehicle: {
    brand: null,
    colour: null,
    model: null,
    registration: null,
    vin: null,
    year: null
  }
};

function category(section) {
    return _.every(section, _.isNull) ? 'empty' :
           _.some(section, _.isNull) ? 'partial' : 'complete';
}

console.log(_.groupBy(sections, category));
<script src="https://cdn.jsdelivr.net/npm/[email protected]/underscore-umd-min.js"></script>

Comments

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.