3

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

3
  • where's the JSON? all I see is an object ... and objects can't be filtered using Array.filter because objects don't have filter method Commented May 21, 2019 at 5:56
  • i am using [templateMapper] see the above code i used [] arrays Commented May 21, 2019 at 5:57
  • Yeah, but that array has one entry - the WHOLE object Commented May 21, 2019 at 6:04

7 Answers 7

4

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);

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

7 Comments

This is the best answer (I was going to post identical code) - I'd add some remarks about Object.fromEntries too
@JaromandaX thanks mate :) i have added some description about code and related link,
@CodeManiac i am getting this error Object.fromEntries is not a function in Node.JS
@user11229655 which version of node you're using mate ?
@CodeManiac i tried in REPL.it node ver seems issue with v10.15.2 . also tried in react its working fine thanks
|
2

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)

Comments

1

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")

2 Comments

This mutates the object rather than creating a new one, which is different from how the filter method works.
It does not mutate the original object - the { ...templateMapper } creates a copy.
0

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);

Comments

0

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);

4 Comments

All the answers here are downvoted except one. Try adding explanation of the code.
I don't see anything wrong with your code, only thing missing is some explanation mate, it is considered as good practice to add explanation to your answer as these will help future readers
I get it, added some explanation. Thank you guys.
@Scofield you can make your code as executable code snippet read here, and here comes your rewards for well detailed answer
-1

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)

Comments

-1

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.

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.