1

Take the following two objects.

filterForm = {'claim_number': null, 'status': 'approved', 'patient': null, 'service_date': null}

this.rows = [
 { "claim_number": '6632224-3', 'patient': 'Janine Soprano', 'allowed_amount':'$100', 'service': 'medical', 'status': 'approved', 'provider': 'Sam Smith'},
 { "claim_number": '3218458-0', 'patient': 'Samatha Snow', 'allowed_amount':'$1100', 'service': 'medical', 'status': 'approved', 'provider': 'John Smith'}

How can I loop through this.rows and check to see which of it's Object keys match the keys of filterForm? I've seen post about checking if an object matches another exactly, but I'm only interested in looping through the object to check which keys match.

Subsequently, once I establish which keys match how can I then check to see which values match?

London804
  • 1,072
  • 1
  • 22
  • 47
  • 2
    Use `Object.keys` to get an array of the given objects keys.. then loop your array of objects and check each individually. – tymeJV Dec 03 '18 at 21:42
  • I've tried to do that, but it always returns false. – London804 Dec 03 '18 at 21:44
  • If you can show me a working example that would be greatly appreciated. – London804 Dec 03 '18 at 21:45
  • 1
    @London804 - better yet, if you post your code, we can show you where you went wrong. – fubar Dec 03 '18 at 21:46
  • What should happen if all properties of filterForm are null? What should happen if two or more fields in filterForm have values? – James Dec 03 '18 at 21:51
  • I'm building a table filter. If they are all null then the rows return unchanged. If two or more fields match then only the rows that match those filters return. – London804 Dec 04 '18 at 16:17

3 Answers3

2

You can use Object.keys to get your filterForm keys:

let availableKeys = Object.keys(filterForm);

Then you need to loop this.rows and find all the keys contained in your above array:

this.rows.forEach(row => {
    let rowKeys = Object.keys(row);
    let matchingRowKeys = availableKeys.filter(k => rowKeys.indexOf(k) > -1);

    //If you then want to check if the values match
    matchingRowKeys.forEach(rk => {
        if (row[rk] === filterForm[rk]) {
            //matching value
            console.log("Found matching key/value", rk, row[rk]);
        }
    });
});

Fiddle: http://jsfiddle.net/2nw3fg0d/

tymeJV
  • 103,943
  • 14
  • 161
  • 157
2

Here is an simple example of how to find the matching keys. This does the following:

  1. Get the filter_form keys by using Object.keys().
  2. Create a Set of those keys for quick lookup using Set.has().
  3. Loop through the rows.
    1. For each row get the keys in the same way as described above.
    2. Use Array.filter() to filter out the keys that are present in filter_keys.

var filter_form, rows, filter_keys, result;

filter_form = { 'claim_number': null, 'status': 'approved', 'patient': null, 'service_date': null };

rows = [
  { 'claim_number': '6632224-3', 'patient': 'Janine Soprano', 'allowed_amount': '$100', 'service': 'medical', 'status': 'approved', 'provider': 'Sam Smith' },
  { 'claim_number': '3218458-0', 'patient': 'Samatha Snow', 'allowed_amount': '$1100', 'service': 'medical', 'status': 'approved', 'provider': 'John Smith' }
];

filter_keys = new Set(Object.keys(filter_form));
result = rows.map(row => Object.keys(row).filter(key => filter_keys.has(key)));

console.log(result);

This answer uses a Set instance to quickly find the keys. If you don't want to use sets replace the following parts.

filter_keys = new Set(Object.keys(filter_form))
// with
filter_keys = Object.keys(filter_form)

key => filter_keys.has(key)
// with 
key => filter_keys.indexOf(key) !== -1

If you're not interested in mapping, but rather want to work with the matching keys in the current iteration use:

let filter_keys = new Set(Object.keys(filter_form));
rows.forEach(row => {
  let matching_keys = Object.keys(row).filter(key => filter_keys.has(key));
  // ...
});
3limin4t0r
  • 19,353
  • 2
  • 31
  • 52
  • What's .log()? Also, this didn't seem to work my console.log for result just returns five empty arrays. I also tried the second version and matching_keys returns an empty array. – London804 Dec 04 '18 at 17:28
  • @London804 That was meant to log each row in-between. I've simplified the answer a bit by removing that part. Check if it works now, if not I'm curious which browser you're using. Your browser might not have [Set support](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set#Browser_compatibility) or [arrow function support](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions#Browser_compatibility). – 3limin4t0r Dec 04 '18 at 19:00
0

You can use flatMap, Array.filter() and the new Set object to get unique keys, while also keeping your code short and readable.

// Get an array of filterForm's keys
const filterFormKeys = Object.keys(filterForm);

// Get a flattened array of this.rows' keys
const rowKeys = this.rows.flatMap(item => Object.keys(item));

// Get keys that exist in both arrays using Array.filter
const existingKeys = rowKeys.filter(key => filterFormKeys.includes(key));

// Use the Set object to get unique keys out of existingKeys
const uniqueExistingKeys = [...new Set(existingKeys)];

console.log(uniqueExistingKeys)

Here's a jsfiddle with an example (Open your console).

Note: You can also use filter instead of Set

const uniqueExistingKeys = existingKeys.filter((value, index) =>
    existingKeys.indexOf(value) === index);

I chose Set because it's more concise. It's all up to you :)

tkore
  • 1,101
  • 12
  • 31
  • Your code is pretty clear, but I don't think I can use it because .flatMap() is experimental. I'm using Angular CLI and I get the ERROR TypeError: this.rows.flatMap is not a function – London804 Dec 04 '18 at 17:07
  • @London804 Well, if you're using `lodash`, there's [lodash flatMap](https://lodash.com/docs/#flatMap). Also, there's [this comment](https://stackoverflow.com/a/52196961/2626340) which you can use to use Array.flatMap. – tkore Dec 04 '18 at 23:17
  • @London804 Also, it is worth noting that even though .flatMap() is experimental, it is very widely used. :) – tkore Dec 04 '18 at 23:30