0

I'm working with a JS data structure that looks something like this:

table = {
  row1: {
    col1: 'A',
    col2: 'B',
    col3: 'C'
  },
  row2: {
    col1: 'D',
    col2: 'A',
    col3: 'F'
  },
  row3: {
    col1: 'E',
    col2: 'G',
    col3: 'C'
  }
};

How would you guys filter this object using JavaScript's native filter/map/reduce functions to produce an array of row object keys that contain the property col3 = "C"?

In this case, it would return ['row1', 'row3'].

This is a solution that I originally came up with based on another answer:

Object.keys(Object.keys(table).reduce(function(accumulator, currentValue) {
  if (table[currentValue].col3==='C') accumulator[currentValue] = table[currentValue];
  return accumulator;
}, {}));

However, I have accepted the solution below using filter() because it's more efficient. The accepted answer is in ES6 syntax, but ES5 syntax was provided by @Paulpro:

Object.keys(table).filter(function(row) {
  return table[row].col3==='C';
});

(Note that there are similar solutions out there, but they use custom functions and are not as concise as the accepted answer provided below.)

thdoan
  • 18,421
  • 1
  • 62
  • 57
  • How would *you* do it? Where's your code? Where are you stuck? –  Apr 24 '18 at 23:32
  • 1
    there is nothing peculiar about that very simple structure – Jaromanda X Apr 24 '18 at 23:47
  • Possible duplicate of [Search a javascript object for a property with a specific value?](https://stackoverflow.com/questions/9422756/search-a-javascript-object-for-a-property-with-a-specific-value) – Heretic Monkey Apr 24 '18 at 23:47
  • @MikeMcCaughan the solution using `filter()` provided here is more concise than the solutions for the linked question. – thdoan Apr 25 '18 at 09:03
  • @CrazyTrain the solution I came up with was not as elegant as the accepted answer (but I didn't have it when I posted the question originally, or else I would've never posed the question): `Object.keys(Object.keys(table).reduce(function(accumulator, currentValue) { if (table[currentValue].col3==='C') accumulator[currentValue] = table[currentValue]; return accumulator; }, {}));` – thdoan Apr 25 '18 at 09:17
  • @JaromandaX pardon my English, I meant to use "particular" instead of "peculiar" because you're right -- there's nothing odd about that data structure. – thdoan Apr 25 '18 at 09:18
  • Then the author of the answer should put their answer on the duplicate. – Heretic Monkey Apr 25 '18 at 16:13
  • @MikeMcCaughan I've done that in the past and it was frowned upon because I guess it's almost like I'm spamming, so now I'm not sure what to do in these cases lol. I'll do it again per your suggestion... – thdoan Apr 26 '18 at 00:08

1 Answers1

2

You could use Object.keys and then filter using the original object:

table = {
  row1: {
    col1: 'A',
    col2: 'B',
    col3: 'C'
  },
  row2: {
    col1: 'D',
    col2: 'A',
    col3: 'F'
  },
  row3: {
    col1: 'E',
    col2: 'G',
    col3: 'C'
  }
};

console.log(Object.keys(table).filter(function(t) { return table[t].col3 === 'C'}))
dave
  • 62,300
  • 5
  • 72
  • 93
  • Thanks @dave. This is elegant, but cannot rely on ES6 -- can you please provide ES5 version? – thdoan Apr 24 '18 at 23:38
  • He asked for ES5, so you should probably avoid using an arrow function. – Paul Apr 24 '18 at 23:38
  • @thdoan Object.keys and Array.prototype.filter are both ES5 so you just need to replace the arrow function with a normal function. It doesn't use `this` so it can be swapped out directly: `function ( t ) { return table[t].col3 === 'C'; }` – Paul Apr 24 '18 at 23:39
  • Thanks for the quick help, guys 8). I'll accept dave using ES5 revision from @Paulpro: `Object.keys(table).filter(function ( t ) { return table[t].col3 === 'C'; })` – thdoan Apr 24 '18 at 23:43