skip to Main Content

I have a Map and I want to convert it to an Object filtering out entries that don’t meet some condition.

My first solution was:

let m = new Map([
    ["key1", { flag: true}],
    ["key2", { flag: false}]
])

o = Object.fromEntries(m.entries()
    .filter(([k,v]) => v.flag)
    .map(([k,v]) => [k, true]));
console.log(o)

However it appears that iterator.filter is not generally available. So I came up with this alternative:

let m = new Map([
    ["key1", { flag: true}],
    ["key2", { flag: false}]
])

let o = Object.fromEntries(
    Array.from(m.entries())
    .map(([k,v]) => [k, v.flag])
    .filter(v => v[1]));

console.log(o)

Which I think is better supported.

Is there a better / faster solution? If iterator.filter was widely supported, would the first solution be a good solution?

2

Answers


  1. It’s safer to start out from keys rather than entries so that you will not have issues with duplicates, otherwise the approach seems to be good:

    let m = new Map([
        ["key1", { flag: true}],
        ["key2", { flag: false}]
    ])
    
    console.log(Object.fromEntries([...m.keys()].filter(item => m.get(item).flag).map(item => [item, m.get(item).flag])));
    Login or Signup to reply.
  2. A more browser-friendly option that doesn’t rely on the new iterator methods is to use a for..of loop and perform the mapping and the filtering in each iteration, for example:

    let m = new Map([
        ["key1", { flag: true}],
        ["key2", { flag: false}]
    ]);
    
    const o = Object.create(null);
    for (const [k, v] of m) {
      if (v.flag)
        o[k] = true;
    }
    console.log(o);

    If you want to stick with using Object.fromEntries(), you can consider making your own map and filter generators that accept an iterable, that way you avoid doing the additional iteration through your iterator to convert it into an array:

    let m = new Map([
        ["key1", { flag: true}],
        ["key2", { flag: false}]
    ]);
    
    function* filter(itr, pred) {
      for (const elem of itr) {
        if (pred(elem))
          yield elem;
      }
    }
    
    function* map(itr, mapper) {
      for (const elem of itr) {
        yield mapper(elem);
      }
    }
    
    const o = Object.fromEntries(map(
      filter(m.entries(), ([k,v]) => v.flag), 
      ([k,v]) => [k, true])
    );
    console.log(o);
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search