user11229655
user11229655

Reputation: 248

Javascript Filter Non-Array JSON Object

I am trying to filter non-array JSON object as the following snippet

const filter = { filterRows: ['one'] };

const templateMapper = {
  'one': {
    title: 'one',
  },
  'two': {
    title: 'two',
  },
  'three': {
    title: 'three',
  },
}

const filterDialogView = filter.filterRows;
const filterTemplateMapper = [templateMapper].filter(row => !filterDialogView.includes(row));
console.log(filterTemplateMapper);

But it's not filtering

I am getting following output

[
  {
    "one": {
    "title": "one"
  },
  "two": {
    "title": "two"
  },
  "three": {
    "title": "three"
  }
 }
]

Desire output

 {
  "two": {
    "title": "two"
  },
  "three": {
    "title": "three"
  }
 }

I want to filter row based on filterRows for example if filterRows contain one as above JSON then one should be removed from the templateMapper

Upvotes: 3

Views: 1318

Answers (7)

Scofjeld
Scofjeld

Reputation: 272

You can use this way:

const filter = { filterRows: ['one'] };

const templateMapper = {
  'one': {
    title: 'one',
  },
  'two': {
    title: 'two',
  },
  'three': {
    title: 'three',
  },
}

// Convert object templateMapper to array with key
const keyArrayTemplateMapper = Object.keys(templateMapper);

// Filter key array
const filterKey = keyArrayTemplateMapper.filter(key => !filter.filterRows.includes(key));

// Using reduce method to return new array
const output = filterKey.reduce((obj, key) => {
    obj[key] = templateMapper[key];
    return obj;
  }, {});

console.log(output);

Upvotes: 0

Code Maniac
Code Maniac

Reputation: 37775

You can use Object.fromEntries to build object back from filtered entries

Here idea is:-

  • First get the entries from template object
  • Filter the entries based on filter value
  • Use Object.fromEntries to build object from filtered entries

const filter = { filterRows: ['one'] };

const template = {'one': {title: 'one',},'two': {title: 'two',},'three': {title: 'three',}}

const filterDialogView = filter.filterRows;
const final = Object.entries(template).filter(([row])=> !filterDialogView.includes(row))
console.log(Object.fromEntries(final));

If you environment doesn't support Object.fromEntries you can use this

const filter = { filterRows: ['one'] };

const template = {'one': {title: 'one',},'two': {title: 'two',},'three': {title: 'three',}}

const filterDialogView = filter.filterRows;
const final = Object.entries(template).filter(([row])=> !filterDialogView.includes(row))

const output = final.reduce((op,[key,value])=>{
  op[key] = value
  return op
},{})
console.log(output);

Upvotes: 4

Maheer Ali
Maheer Ali

Reputation: 36594

You can filter() objects. You should filter() the entries of object and then convert it to object again using Object.fromEntries()

const filter = { filterRows: ['one'] };

const templateMapper = { 'one': { title: 'one', }, 'two': { title: 'two', }, 'three': { title: 'three', }, }

const filterDialogView = filter.filterRows;
const filterTemplateMapper = Object.fromEntries(
             Object.entries(templateMapper)
                   .filter(row => !filterDialogView.includes(row[0].title))
             );
console.log(filterTemplateMapper);

If Object.fromEntries() is not supported by your browser then use reduce()

const filter = { filterRows: ['one'] };

const templateMapper = { 'one': { title: 'one', }, 'two': { title: 'two', }, 'three': { title: 'three', }, }

const filterDialogView = filter.filterRows;
const filterTemplateMapper = Object.entries(templateMapper)
                   .filter(row =>!filterDialogView.includes(row[0].title))
                   .reduce((ac,[k,v]) => (ac[k] = v,ac),{});
console.log(filterTemplateMapper);

Upvotes: 0

Soviut
Soviut

Reputation: 91704

The filter() function is only available on arrays. In order to get the same behaviour with an object, you need to use the object's entries().

const filter = {
  filterRows: ['one']
}

const templateMapper = {
  'one': {
    title: 'one',
  },
  'two': {
    title: 'two',
  },
  'three': {
    title: 'three',
  },
}

const filteredMapper = Object.entries(templateMapper).reduce((acc, [key, value]) => {
  // if the key is not in the filtered list, add this entry to the object
  if (!filter.filterRows.includes(key)) {
    acc[key] = value
  }

  return acc
}, {}) // pass in empty object as initial value of accumulator

console.log(filteredMapper)

The way this works is we first get the entries (key/value pairs) from templateMapper. We then take those entries and reduce them. A reduce takes several arguments including an "accumulator" which is what collects the fields we want to keep. We "destructure" key and value so that we can check if the key is in the filter list. If it is not going to be filtered, we add it ot the accumulator. We then return the accumulator for the next iteration of the reduce. Finally, we pass in an empty object as the initial value for the accumulator on the first iteration.

Upvotes: -1

brk
brk

Reputation: 50346

Instead of modifying the original object create a copy of it and delete the unwanted keys. For delete you can use delete keyword. Iterated the filterRows array and then use delete to remove the keys from the copied object

const filter = {
  filterRows: ['one']
};

const templateMapper = {
  'one': {
    title: 'one',
  },
  'two': {
    title: 'two',
  },
  'three': {
    title: 'three'
  },
}


let newObj = JSON.parse(JSON.stringify(templateMapper));
filter.filterRows.forEach(function(item) {
  if (newObj.hasOwnProperty(item)) {
    delete newObj[item]
  }
});
console.log(newObj)

Upvotes: -1

adiga
adiga

Reputation: 35259

You could filter the entries of the object first. Then use Object.fromEntries() to create a new object from those filtered entries.

const filter = { filterRows: ['one'] };

const templateMapper = {
  'one': {
    title: 'one',
  },
  'two': {
    title: 'two',
  },
  'three': {
    title: 'three',
  },
}

const filteredObject = Object.fromEntries(
    Object.entries(templateMapper).filter(([k]) => !filter.filterRows.includes(k))
)

console.log(filteredObject)

Upvotes: 2

CertainPerformance
CertainPerformance

Reputation: 371193

One option is to create a copy of the templateMapper object, then iterate through the filterRows and delete each associated key:

const filter = {
  filterRows: ['one']
};

const templateMapper = {
  'one': {
    title: 'one',
  },
  'two': {
    title: 'two',
  },
  'three': {
    title: 'three',
  },
};


const filterTemplateMapper = { ...templateMapper };
filter.filterRows.forEach((key) => {
  delete filterTemplateMapper[key];
});
console.log(filterTemplateMapper);

(also, as comment notes, There's no such thing as a "JSON Object")

Upvotes: 1

Related Questions