suuuriam
suuuriam

Reputation: 747

Filter nested object

I receive an object that looks like this:

 this.tokensData = {
    O: {
        id: 0,
        name: value1,
        organization: organization1,
        ...,
       },
    1: {
        id: 1,
        name: value1,
        organization: organization1,
        ...,
        },
    2: {
        id: 2,
        name: value2,
        organization: organization2,
        ...,
        },
    ...
   }

I want to filter by id and remove the Object which id matches the id I receive from the store. What I tried so far:

const filteredObject = Object.keys(this.tokensData).map((token) => {
  if (this.$store.state.id !== this.tokensData[token].id) {
    return this.tokensData[token];
  }
});

This replaces the Object with undefined - which would work for my purposes but is obviously not ideal. Any help is much appreciated!

Upvotes: 8

Views: 4636

Answers (4)

StepUp
StepUp

Reputation: 38114

Try to use Object.entries and then Object.fromEntries() to create an object from a list of key-value pairs:

const store = [0 , 1];

const result = Object
   .entries(tokensData)
   .filter(([k, v]) => !store.some(s => s == v.id));

console.log(Object.fromEntries(result));

An example:

const tokensData = {
   O: {
       id: 0,
       name: '',
       organization: '',
      },
   1: {
       id: 1,
       name: '',
       organization: '',
       },
   2: {
       id: 2,
       name: '',
       organization: '',
       }
  }

const store = [0 , 1];

const result = Object
    .entries(tokensData)
    .filter(([k, v]) => !store.some(s => s == v.id));

console.log(Object.fromEntries(result));

Upvotes: 6

Marco
Marco

Reputation: 5109

The problem with undefined is caused by using this in your arrow function. Javascript scoping gives a different meaning to this if the function is a arrow function.

Furthermore I suggest to use filter.

.map is used to transform A -> B.

.filter should be used to filter out objects.

Now if we combine that this would become something like this.

function filterById(token) {
  return this.$store.state.id !== this.tokensData[token].id;
}

function getTokenData(token) {
  return this.tokensData[token]
}

const token = Object.keys(this.tokensData)
  .filter(filterById)
  .map(getTokenData);
});

Please note that I'm not using arrow functions. Arrow function can't refer to this due to the way javascript handles scoping.

An alternative approach could be to reference this into a variable, so your arrow function can access the variable.

const self = this;
const token = Object.keys(this.tokensData)
  .filter(token => self.$store.state.id !== self.tokensData[token].id)
  .map(token => self.tokensData[token]);

Too make it even nicer you could utilize Object.entries. This will return an array of key and value, which you can destructure using es6 syntax as following [key, value].

const self = this;
const token = Object.entries(this.tokensData)
  .filter(([key, value]) => self.$store.state.id !== value.id)
  .map(([key, value]) => value);

Upvotes: 1

Stefan Bajić
Stefan Bajić

Reputation: 497

You can do this by using Object.entries and Object.fromEntries:

const filteredObject = Object.fromEntries(
  Object.entries(this.tokensData).filter(
    ([key, value]) => value.id !== this.$store.state.id
  )
)

Upvotes: 3

Rob Brander
Rob Brander

Reputation: 3781

This can be done by cloning the object and removing the object at the ID:

const removeObjectByID = (obj, id) => {
  // first create a copy of the object
  const copy = JSON.parse(JSON.stringify(obj))
  // next, delete the one entry you don't want
  delete copy[id]
  // finally, return the new object
  return copy
}

// Test
const data = {a:1, b: 2, c: 3}

console.log(removeObjectByID(data, 'b')) // { a: 1, c: 3 }

Upvotes: 1

Related Questions