1

I have JSON data that I want to filter that is an array type.

{
    "1": {
      "enemy_id": 1,
      "ai_": 0,
      "ailmentcast1": -1
      },
    "9": {
      "enemy_id": 2,
      "ai_": 5,
      "ailmentcast1": 2
      },
    "2": {
      "enemy_id": 4,
      "ai_": 10,
      "ailmentcast1": 7
      },
    "29": {
      "enemy_id": 1,
      "ai_": 1,
      "ailmentcast1": 15
      },
    "17": {
      "enemy_id": 3,
      "ai_": 7,
      "ailmentcast1": 10
      }
}

I want to filter out sets with enemy_id != 1. So a return would look like this:

{
    "9": {
      "enemy_id": 2,
      "ai_": 5,
      "ailmentcast1": 2
      },
    "2": {
      "enemy_id": 4,
      "ai_": 10,
      "ailmentcast1": 7
      },
    "17": {
      "enemy_id": 3,
      "ai_": 7,
      "ailmentcast1": 10
      }
}

I have a functions I have tried but I'm having a hard time with the formatting.

function find_in_object(my_object, my_criteria){
  return my_object.filter(function(obj) {
    return Object.keys(my_criteria).every(function(c) {
      return obj[c] == my_criteria[c];
    });
  });

}

And the code I ran that didn't work:

  var newdata = [];
  var filter = JSON.parse(content, function(key, value) { 
      if ( value.enemy_id !== 1 ) newdata.push(value); 
      return value; });

Any help would be greatly appreciated!

1
  • 1
    The second argument to JSON.parse is a function that can clean up the whole object before it's returned. It looks like here you're presuming it gives you individual values, which it doesn't. Commented Sep 22, 2020 at 21:25

6 Answers 6

1

I think you're really close here, where you can define a separate matching function like:

function entryMatches(entry, criteria) {
  return Object.keys(criteria).every(k => entry[k] == criteria[k]);
}

Then a filtering function that engages that on each key, but still returns the same type of structure:

function dataFilter(data, criteria) {
  let result = { };

  Object.keys(data).filter(k => entryMatches(data[k], criteria)).forEach(k => {
    result[k] = data[k];
  });

  return result;
}

Where you get results like this:

function entryMatches(entry, criteria) {
  return Object.keys(criteria).every(k => entry[k] == criteria[k]);
}

function dataFilter(data, criteria) {
  let result = { };

  Object.keys(data).filter(k => entryMatches(data[k], criteria)).forEach(k => {
    result[k] = data[k];
  });

  return result;
}

const data = {
  1: {
    enemy_id: 1,
    ai_: 0,
    ailmentcast1: -1
  },
  9: {
    enemy_id: 2,
    ai_: 5,
    ailmentcast1: 2
  },
  2: {
    enemy_id: 4,
    ai_: 10,
    ailmentcast1: 7
  },
  29: {
    enemy_id: 1,
    ai_: 1,
    ailmentcast1: 15
  },
  17: {
    enemy_id: 3,
    ai_: 7,
    ailmentcast1: 10
  }
};

console.log(dataFilter(data, { enemy_id: 1, ailmentcast1: -1 }));
// { '1': { enemy_id: 1, ai_: 0, ailmentcast1: -1 } }

console.log(dataFilter(data, { enemy_id: 2 }));
// { '9': { enemy_id: 2, ai_: 5, ailmentcast1: 2 } }

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

Comments

1

Try the snippet below. It actually is a one-liner and it changes the keys of the initial object.

let q = {
    "1": {
      "enemy_id": 1,
      "ai_": 0,
      "ailmentcast1": -1
      },
    "9": {
      "enemy_id": 2,
      "ai_": 5,
      "ailmentcast1": 2
      },
    "2": {
      "enemy_id": 4,
      "ai_": 10,
      "ailmentcast1": 7
      },
    "29": {
      "enemy_id": 1,
      "ai_": 1,
      "ailmentcast1": 15
      },
    "17": {
      "enemy_id": 3,
      "ai_": 7,
      "ailmentcast1": 10
      }
};
let output = Object.assign({},Object.values(q).filter(x => x.enemy_id != 1));
console.log(output);

Use Object.values to turn your object to an Array. Then use Array.filter() to actually filter out the entries you want. Use Object.assign() to keep the Object datatype instead of the Array.

Comments

0

You are already using Object.entries to turn the object in an array. Now you'll have an array of key-value pairs like:

[
  "1", // key
  { // value
    "enemy_id": 1,
    "ai_": 0,
    "ailmentcast1": -1
  }
]

From here you can access the enemy_id property in the value and use Array.prototype.filter to only return the key-value pairs where the enemy_id is a match with the id given.

Then turn the array of entries back into an object with Object.fromEntries. It is basically the reverse of Object.entries.

const data = {
  "1": {
    "enemy_id": 1,
    "ai_": 0,
    "ailmentcast1": -1
  },
  "9": {
    "enemy_id": 2,
    "ai_": 5,
    "ailmentcast1": 2
  },
  "2": {
    "enemy_id": 4,
    "ai_": 10,
    "ailmentcast1": 7
  },
  "29": {
    "enemy_id": 1,
    "ai_": 1,
    "ailmentcast1": 15
  },
  "17": {
    "enemy_id": 3,
    "ai_": 7,
    "ailmentcast1": 10
  }
};

const filterEnemyById = (data, id) => Object.fromEntries(
  Object.entries(data).filter(([key, { enemy_id }]) => 
    enemy_id !== id
  )
);

const result = filterEnemyById(data, 1);
console.log(result);

1 Comment

Worked great! Thank you for your time 🙏🏼
0

You can use object.entries and then reduce to filter out the records

const input = {
  "1": {
    "enemy_id": 1,
    "ai_": 0,
    "ailmentcast1": -1
  },
  "9": {
    "enemy_id": 2,
    "ai_": 5,
    "ailmentcast1": 2
  },
  "2": {
    "enemy_id": 4,
    "ai_": 10,
    "ailmentcast1": 7
  },
  "29": {
    "enemy_id": 1,
    "ai_": 1,
    "ailmentcast1": 15
  },
  "17": {
    "enemy_id": 3,
    "ai_": 7,
    "ailmentcast1": 10
  }
}


const result = Object.entries(input).reduce((acc, [key, val]) => {
  if (val['enemy_id'] !== 1) {
    acc[key] = val;
  }
  return acc;
}, {})

console.log(result)

Comments

0

You can use a simple for to loop and remove unwanted eles:

for ..in: The for...in statement iterates over all enumerable properties of an object that are keyed by strings (ignoring ones keyed by Symbols), including inherited enumerable properties.

var data = {
    "1": {
        "enemy_id": 1,
        "ai_": 0,
        "ailmentcast1": -1
    },
    "9": {
        "enemy_id": 2,
        "ai_": 5,
        "ailmentcast1": 2
    },
    "2": {
        "enemy_id": 4,
        "ai_": 10,
        "ailmentcast1": 7
    },
    "29": {
        "enemy_id": 1,
        "ai_": 1,
        "ailmentcast1": 15
    },
    "17": {
        "enemy_id": 3,
        "ai_": 7,
        "ailmentcast1": 10
    }
};

for (e in data) {
    if (data[e].enemy_id == 1) {
        delete data[e];
    }
}


console.log(data)

Comments

0

You probably want this:

const filtered = Object.entries(data).filter(entry => entry[1].enemy_id != 1).reduce((dict, entry) => {
  dict[entry[0]] = entry[1];
  return dict;
}, {});

it will return your data in the initial form.

https://jsfiddle.net/ea0zpxkr/

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.