LearningReact
LearningReact

Reputation: 113

new Map() State get specific key

I have a state checkedItems: new Map();

and when I'm trying to console.log(checkedItem) i get this:

Map(3) {"1" => true, "1.5" => true, "2" => false}

How can I get only the true one in an array.

Upvotes: 3

Views: 247

Answers (1)

VLAZ
VLAZ

Reputation: 28969

Maps have the entries() method which returns an iterator over the key-value pairs. Iterators are lazy, so you have to consume it to transform it. One way is to turn into an array and then use Array#filter and Array#map to get the keys:

Array.from(checkedItems.entries())
    .filter(([key, value]) => value)
    .map(([key]) => key)

However, there is a better way to do this lazily using generators:

function* filter(predicate, it) {
  for (const item of it) {
    if (predicate(item))
      yield item;
  }
}

function* map(fn, it) {
  for (const item of it) {
    yield fn(item);
  }
}


const checkedItems = new Map()
  .set("1"  , true)
  .set("1.5", true)
  .set("2"  , false);
  
const iterator = checkedItems.entries();
const onlyTrue = filter(([key, value]) => value, iterator);
const onlyTrueKeys = map(([key]) => key, onlyTrue);

console.log(Array.from(onlyTrueKeys));

This will only generate a single array at the end.

The filter and map generator functions can be combined together

const onlyTrueKeys = map(
  ([key]) => key,
  filter(
    ([key, value]) => value,
    checkedItems.entries()
  )
);

But it might be easier to partially apply and then compose them with a helper function:

function* filter(predicate, it) {
  for (const item of it) {
    if (predicate(item))
      yield item;
  }
}

function* map(fn, it) {
  for (const item of it) {
    yield fn(item);
  }
}

function transform(iterator, ...transformers) {
  return transformers.reduce((it, transform) => transform(it), iterator);
}


const checkedItems = new Map()
  .set("1"  , true)
  .set("1.5", true)
  .set("2"  , false);

const onlyTrueKeys = transform(
  checkedItems.entries(),
  
  filter.bind(null, ([key, value]) => value),
  map.bind(null, ([key]) => key),
  Array.from
);

console.log(onlyTrueKeys);

This can also be made into a class, if you prefer:

function* filter(it, pred) {
  for (const item of it) {
    if (pred(item))
      yield item;
  }
}

function* map(it, fn) {
  for (const item of it) {
    yield fn(item);
  }
}

class LazyTransformer {
  constructor(iterator) {
    this.iterator = iterator;
  }
  
  filter(predicate) {
    this.iterator = filter(this.iterator, predicate);
    return this;
  }
  
  map(fn) {
    this.iterator = map(this.iterator, fn);
    return this;
  }
  
  toArray() {
    return Array.from(this.iterator);
  }
}


const checkedItems = new Map()
  .set("1"  , true)
  .set("1.5", true)
  .set("2"  , false);

const transformer = new LazyTransformer(checkedItems.entries());

transformer
  .filter(([key, value]) => value)
  .map(([key]) => key);

console.log(transformer.toArray());

Upvotes: 2

Related Questions