0

I have an array of objects like this,

value = [
  {"f1_x":1, "f1_y":3, "f2_x": 5},
  {"f1_x":2, "f2_y":4, "f2_x": 6}
]

Now, I only want to keep key/value pairs where key ends with _x. So, the above would look like this,

value = [
  {"f1_x":1, "f2_x": 5},
  {"f1_x":2, "f2_x": 6}
]

I used the following, but is there any more elegant way of doing the same?

var x = value.map(e => {
  r = {}
  for (const f in e)
    if (f.toLowerCase().endsWith("_x"))
      r[f] = e[f]
  return r
})
VLAZ
  • 26,331
  • 9
  • 49
  • 67
MetallicPriest
  • 29,191
  • 52
  • 200
  • 356
  • What's wrong with the current approach? More elegant according to whom? – evolutionxbox May 25 '21 at 09:41
  • I meant more succinct. – MetallicPriest May 25 '21 at 09:41
  • 1
    Isn't this better suited for https://codereview.stackexchange.com/? Unless there's something wrong with the current approach? – evolutionxbox May 25 '21 at 09:43
  • 1
    You should check dev twitter from last 3-4 days. There was a huge discussion on this very question. https://twitter.com/dan_abramov/status/1396813335795011587 this summs it up. – The Fool May 25 '21 at 09:47
  • [There's no such thing as a JSON Object](http://benalman.com/news/2010/03/theres-no-such-thing-as-a-json/). You have [plain objects expressed as object literal notation](https://stackoverflow.com/questions/2904131/what-is-the-difference-between-json-and-object-literal-notation) – VLAZ May 25 '21 at 09:49
  • @TheFool Could you write an answer with the relevant points? – Mast May 25 '21 at 09:50
  • 1
    Add a `const` to `r`. Otherwise, it looks fine. There are plenty of alternatives like `reduce` or `Object.fromEntries` with `filter` etc. Whether they are elegant is opinion-based. – adiga May 25 '21 at 09:51
  • Can you define "more elegant"? What are the metrics to determine it? – VLAZ May 25 '21 at 09:52
  • Duplicate of [From an object, extract properties with names matching a test](https://stackoverflow.com/questions/60431862) – adiga May 25 '21 at 09:57
  • 1
    The only problem in your code is the missing `let` in `r = {}` – georg May 25 '21 at 10:53

4 Answers4

3

You can use Object.prototype.fromEntries and Object.prototype.entries

const value = [
  {"f1_x":1, "f1_y":3, "f2_x": 5},
  {"f1_x":2, "f2_y":4, "f2_x": 6}
];

const result = value.map((obj) => Object.fromEntries(Object.entries(obj).filter(([key]) => key.endsWith("_x"))));
console.log(result)
Krzysztof Krzeszewski
  • 5,912
  • 2
  • 17
  • 30
1

Not quite sure if it's any better, but here's a single liner:

let value = [
    {"f1_x":1, "f1_y":3, "f2_x": 5},
    {"f1_x":2, "f2_y":4, "f2_x": 6}
];

let newValue = value.map(e => Object.fromEntries(Object.entries(e).filter(p => p[0].toLowerCase().endsWith("_x"))));

console.log(newValue);
NullDev
  • 6,739
  • 4
  • 30
  • 54
1

I can write it like this for a little better readability.

var x = value.map(e => {
let r = {};
let newKeys = Object.keys(e).filter((x) => x.toLowerCase().endsWith("_x"));
newKeys.forEach((x) => r[x] = e[x]);
return r
});
Tushar Shahi
  • 16,452
  • 1
  • 18
  • 39
1

In the following method, you can use Array methods explicitly.

let value = [
  {"f1_x":1, "f1_y":3, "f2_x": 5},
  {"f1_x":2, "f2_y":4, "f2_x": 6}
]

let filtered = value.map(obj => 
  Object.keys(obj).reduce((a, c) => {  
    c[c.length - 1] === 'x' ? a[c] = obj[c] : null;    
    return a
  }, {})

)

console.log(filtered);
Charlie
  • 22,886
  • 11
  • 59
  • 90