1

I have the following data structure,

var stat = {
  meta : 0,

  added : {
    menuSessions: {
      items: 0,
      fields: 0
    },

    menuCats: {
      items: 0,
      fields: 0
    },

    menuItems: {
      items: 0,
      fields: 0
    }
  },

  updated: {
    menuSessions: {
      items: 0,
      fields: 0
    },

    menuCats: {
      items: 0,
      fields: 3
    },

    menuItems: {
      items: 3,
      fields: 0
    }
  },

  deleted: {
    menuSessions: 1,
    menuCats: 10,
    menuItems: 0
  }
};

and want to derive a structure as follows using lodash,

var stat = {
  //meta not shown
  //added not shown
  updated: {
    menuCats: {
      //items not show etc..
      fields: 3
    },

    menuItems: {
      items: 3,
    }
  },

  deleted: {
    menuSessions: 1,
    menuCats: 10,
  }
};

I tried many approaches such as using filter method as follows or pure JS (if easier),

var json  = _.filter(stat, function(statEle){

    return statEle > 0 || ((statEle.added && statEle.added.menuSessions) && (statEle.added.menuSessions.items > 0 || statEle.added.menuSessions.fields > 0))
    || ((statEle.updated && statEle.updated.menuSessions) && (statEle.updated.menuSessions.items > 0 || statEle.updated.menuSessions.fields > 0))
    || ((statEle.deleted && statEle.deleted.menuSessions) && (statEle.deleted.menuSessions > 0))
    || ((statEle.added && statEle.added.menuCats) && (statEle.added.menuCats.item > 0 || statEle.added.menuCats.fields > 0))
    || ((statEle.added && statEle.added.menuItems) && (statEle.added.menuItems.items > 0 ||  statEle.added.menuItems.fields > 0))
    || ((statEle.deleted && statEle.deleted.menuItems) && (statEle.deleted.menuItems > 0))
    || ((statEle.deleted && statEle.deleted.menuCats) && (statEle.deleted.menuCats > 0));

  });

as shown in - Lodash: how do I use filter when I have nested Object? and failed as this structure requires to filter dynamic property names.

I am quite new to the JSON filter and lodsash stacks and would appreciate any useful reference/ examples to get me going to accomplish this :) thanks

Community
  • 1
  • 1
Hasitha Shan
  • 2,900
  • 6
  • 42
  • 83

1 Answers1

1

If you combine _.mapValues and _.pickBy - there's your answer: pickByRecursive.

var pickByRecursive = function (object, predicate) {
    return _.pickBy(_.mapValues(object, function (value) {
        return _.isObject(value) ? pickByRecursive(value, predicate) : value;
    }), function (value) {
        return _.isObject(value) ? !_.isEmpty(value) : predicate(value);
    });
};

Or with _.chain:

var pickByRecursive = function (object, predicate) {
    return _.chain(object)
        .mapValues(function (value) {
            return _.isObject(value) ? pickByRecursive(value, predicate) : value;
        })
        .pickBy(function (value) {
            return _.isObject(value) ? !_.isEmpty(value) : predicate(value);
        })
    .value();
};

Use it like this:

pickByRecursive(stat, function (value) {
    return value > 0;
});
Radosław Miernik
  • 4,004
  • 8
  • 33
  • 36