Move elements from one List to another with Immutable.js

1k views Asked by At

I'm playing with Immutable.js. I came across this problem and I wasn't able to find a nice solution: I have two lists, A and B, and I want to filter out some elements from the list A using a custom predicate function and add them to the list B. Both are immutable.

The obvious problem here is that the return value of A.filter(predicate) is a new updated instance and the removed elements are lost. I could first add those filtered elements:

B = B.concat(A.filterNot(predicate));
A = A.filter(predicate);

That would mean cycling over the original list twice. The only way around this is to add a side effect to the filtering function:

let tmp = [];
B = B.filter(el => { 
    if (!predicate(el)) {
        tmp.push(el);
        return false;
    } else return true;
});
A = A.concat(tmp);

That however looks a bit hacky. I don't think the filter method is supposed to be used this way. Is there a better solution?

1

There are 1 answers

1
Sze-Hung Daniel Tsui On

Assuming here B is the array you want to filter, and A gets the filtered elements concatenated to it: (like your second code example), I think this is the best you can do.

A.withMutations( (list) => {
  B = B.filter( 
    (el) => { 
      if (!predicate(el)) {
          list.push(el);
          return false;
      } else return true;
    }
  );
  return list;
});

or, arguably more readable:

A.withMutations( (list) => {
  B = B.filter( (el) => { return (!predicate(el)) ? !!list.push(el) : true; 
      });
  return list;
});

If you find yourself moving items from one list to another often, it is probably best to write a method, transferTo that does the above.

From withMutations:

Note: Not all methods can be used on a mutable collection or within withMutations! Only set, push, pop, shift, unshift and merge may be used mutatively.