2
\$\begingroup\$

I have been using reduce() method to group by Open and Closes statuses (Status_111, Status_222, etc) which then creates an array of which Ids (item.Id) it is associated with.

Code is working and with an expected result, however, I feel like code could have been written better because as you can see I have been using too many if conditions for creating blank arrays to check if (item.Open && !obj[item.Open]) and if (item.Close && !obj[item.Close]) exists - how would you improve the code?

const items = [
  { Id: 100, Open: 'Status_111', Close: 'Status_111' },
  { Id: 200, Open: 'Status_111', Close: 'Status_222' },
  { Id: 300, Open: 'Status_333', Close: 'Status_444' }
]

function groupByOpenAndClose(items) {
  return items.reduce(function (obj, item) {
    if (item.Open && !obj[item.Open]) {
        obj[item.Open] = {
          Open: [],
          Close: []
        }
    }

    if (item.Close && !obj[item.Close]) {
      obj[item.Close] = {
        Open: [],
        Close: []
      }
    }

    if (obj[item.Open]) {
      obj[item.Open].Open.push(item.Id)
    }

    if (obj[item.Close]) {
      obj[item.Close].Close.push(item.Id)
    }

    return obj
  }, {});
}

console.log(groupByOpenAndClose(items));

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

Like this:

function groupByOpenAndClose(items) {
  return items.reduce((obj, item) => {
    return {
      ...obj,
      [item.Close]: {
        Close: [...(obj[item.Close]?.Close ?? []), item.Id],
        Open: obj[item.Close]?.Open ?? []
      },
      [item.Open]: {
        Open: [...(obj[item.Open]?.Open ?? []), item.Id],
        Close: obj[item.Open]?.Close ?? []
      }
    }
  }, {});
}

But in all seriousness, it is not much you can do without creating some structure of your own - something like default dict in python:

class DefaultDict {
  constructor(defFactory) {
    this.defFactory = defFactory;
    this.dict = {}
  }
  
  getOrDefault(status) {
    if(!status) return;
    if(!this.dict[status]) this.dict[status] = this.defFactory();
    
    return this.dict[status];
  }
}

function groupByOpenAndClose(items) {
  return items.reduce(function(obj, item) {
    obj.getOrDefault(item.Close)?.Close.push(item.Id);
    obj.getOrDefault(item.Open)?.Open.push(item.Id);
    return obj;
  }, new DefaultDict(() => ({ Close: [], Open: [] })));
}

console.log(groupByOpenAndClose(items).dict);
\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.