2

I have an object that I need to turn into an array of data, based on a specific key.

Here is my original object:

{
  "centerID": "6",
  "marketID": "1",
  "invoiceGroupID": "4",
  "blocks": [
    {
      "name": "Monday-Friday 11:00AM-3:00PM",
      "isChecked": true
    },
    {
      "name": "Monday-Friday 7:00AM-11:00AM",
      "isChecked": false
    },
    {
      "name": "Saturday-Sunday 2:00PM-8:00PM",
      "isChecked": true
    }
  ],
  "bankedHoursYN": "N"
}

Currently, I am using filter to only provide me the blocks where isChecked = true by using _.filter(this.mappingForm.get('blocks').value, { isChecked: true }).

The result of this leaves me with:

{
  "centerID": "6",
  "marketID": "1",
  "invoiceGroupID": "4",
  "blocks": [
    {
      "name": "Monday-Friday 11:00AM-3:00PM",
      "isChecked": true
    },
    {
      "name": "Saturday-Sunday 2:00PM-8:00PM",
      "isChecked": true
    }
  ],
  "bankedHoursYN": "N"
}

This works fine, leaving me with an array of two objects.

My end result is to just have an array of the name values.

Expected Output:

{
  "centerID": "6",
  "marketID": "1",
  "invoiceGroupID": "4",
  "blocks": ['Monday-Friday 11:00AM-3:00PM','Saturday-Sunday 2:00PM-8:00PM'],
  "bankedHoursYN": "N"
}

Does lodash have a built in way to handle this?

Heretic Monkey
  • 11,687
  • 7
  • 53
  • 122
SBB
  • 8,560
  • 30
  • 108
  • 223
  • what is the expected output? – brk Aug 27 '18 at 14:56
  • @brk `"blocks": ['Monday-Friday 11:00AM-3:00PM','Saturday-Sunday 2:00PM-8:00PM'],` – SBB Aug 27 '18 at 14:57
  • i don't see difference between one and other – Erubiel Aug 27 '18 at 14:59
  • @Erubiel The original object has `blocks` which is an array of objects. I want that to only be an array of values (not contain `name` and `isChecked`). – SBB Aug 27 '18 at 15:00
  • 1
    Possible duplicate of [From an array of objects, extract value of a property as array](https://stackoverflow.com/questions/19590865/from-an-array-of-objects-extract-value-of-a-property-as-array) – Heretic Monkey Aug 27 '18 at 15:03
  • Why would you want lodash for the task? Javascript can do this with no extras needed. – connexo Aug 27 '18 at 15:16
  • @connexo - `lodash` is already being used elsewhere in this project for other things, was just checking to see if there were ways to do it in the library since it was already included. – SBB Aug 27 '18 at 15:17
  • @SBB I see, yet I don't think lodash is making things any easier here. – connexo Aug 27 '18 at 15:19
  • Is your question answered? If so, please pick an answer. If not, please comment on the answers given. – connexo Aug 27 '18 at 15:54

5 Answers5

1

You can chain _.filter(), and _.map() to get the just the names of the blocks with isChecked: true:

const data = { "centerID": "6", "marketID": "1", "invoiceGroupID": "4", "blocks": [ { "name": "Monday-Friday 11:00AM-3:00PM", "isChecked": true }, { "name": "Monday-Friday 7:00AM-11:00AM", "isChecked": false }, { "name": "Saturday-Sunday 2:00PM-8:00PM", "isChecked":true } ], "bankedHoursYN": "N" };

data.blocks = _(data.blocks)
  .filter('isChecked')
  .map('name')
  .value();
  
console.log(data);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
Ori Drori
  • 183,571
  • 29
  • 224
  • 209
0

Does lodash have a built in way to handle this?

I don't know, but Javascript has.

Use Array.prototype.filter() and chain Array.prototype.map():

let obj = {
  "centerID": "6",
  "marketID": "1",
  "invoiceGroupID": "4",
  "blocks": [
    {
      "name": "Monday-Friday 11:00AM-3:00PM",
      "isChecked": true
    },
    {
      "name": "Monday-Friday 7:00AM-11:00AM",
      "isChecked": false
    },
    {
      "name": "Saturday-Sunday 2:00PM-8:00PM",
      "isChecked": true
    }
  ],
  "bankedHoursYN": "N"
}

obj.blocks = obj.blocks.filter(i=>i.isChecked).map(i=>i.name)

console.log(obj)

If you need to use ES5:

obj.blocks = obj.blocks
  .filter(function(i) { return i.isChecked })
  .map(function(i) { return i.name });
connexo
  • 53,704
  • 14
  • 91
  • 128
0

After filtering the blocks, you can use map and concat to join the name of block object.

var data = { "centerID": "6", "marketID": "1", "invoiceGroupID": "4", "blocks": [ { "name": "Monday-Friday 11:00AM-3:00PM", "isChecked": true }, { "name": "Monday-Friday 7:00AM-11:00AM", "isChecked": false }, { "name": "Saturday-Sunday 2:00PM-8:00PM", "isChecked":true } ], "bankedHoursYN": "N" };
data.blocks = _.chain(data.blocks).filter({ isChecked: true }).map(({name}) => name).concat().value();
console.log(data);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
Hassan Imam
  • 21,956
  • 5
  • 41
  • 51
0

If you are searching for what built in functionality is there for performing map and filter together, then you can always combine map and filter operation in a single reduce (whether in lodash or in plain vanilla JS) to iterate the array only once.

So, the structure will be:

<Array>.reduce((res, each) => (<filter condition> && res.push(<mapped data>), res), [])

So, In your case: obj.blocks.reduce((r, b) => (b.isChecked && r.push(b.name), r), [])

var obj = {
  "centerID": "6",
  "marketID": "1",
  "invoiceGroupID": "4",
  "blocks": [
    {
      "name": "Monday-Friday 11:00AM-3:00PM",
      "isChecked": true
    },
    {
      "name": "Monday-Friday 7:00AM-11:00AM",
      "isChecked": false
    },
    {
      "name": "Saturday-Sunday 2:00PM-8:00PM",
      "isChecked": true
    }
  ],
  "bankedHoursYN": "N"
};

obj.blocks = obj.blocks.reduce((r, b) => (b.isChecked && r.push(b.name), r), []);

console.log(obj)

However, I will suggest you not to mutate and make a copy of your original object and override the blocks on the copy to make it a fresh output.

Koushik Chatterjee
  • 4,106
  • 3
  • 18
  • 32
0

var data.blocks = .map(.filter(data.blocks,function(o) { return o.isChecked===true; }),'name');

Prateek
  • 28
  • 4