2

Is there any shorthand option to remove array from array of arrays using Ramda library ?

Items to remove: [[1, 2], [a, b]]
Remove from: [[g, d], [5, 11], [1, 2], [43, 4], [a, b]]

Result: [[g, d], [5, 11], [43, 4]]
2
  • Are those arrays references of same array or are they created separately? Commented Nov 19, 2017 at 22:45
  • Well didn't my answer below give a solution to your problem?! Commented Nov 20, 2017 at 13:00

5 Answers 5

3

Use R.difference with R.flip:

const data = [['g', 'd'], [5, 11], [1, 2], [43, 4], ['a', 'b']]
const itemsToRemove = [[1, 2], ['a', 'b']]

const fn = R.flip(R.difference)(itemsToRemove);

console.log(fn(data))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>

Sign up to request clarification or add additional context in comments.

2 Comments

It's a proper solution but I faced efficiency problems using this solution. Finally I've decided to write my own function which is much faster. I've transformed each array into string and removed matching strings from my array then transformed it again into array.
@PiotrO - post your final solution as an answer.
2

This is probably the best answer

use R.reject and R.contains

var Itemstoremove =  [[1, 2], [a, b]]
var Removefrom =  [[g, d], [5, 11], [1, 2], [43, 4], [a, b]]

var Result = R.reject(R.contains(R.__, Itemstoremove), Removefrom)

console.log(Result)

Comments

1

A combination of R.reject, R.either and R.equals can achieve this.

const data = [['g', 'd'], [5, 11], [1, 2], [43, 4], ['a', 'b']]

const fn = R.reject(R.either(R.equals(['a', 'b']), R.equals([1, 2])))

console.log(fn(data))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>

1 Comment

This works, but using R.contains(R.__, [['a', 'b'], [1, 2]]) as a predicate makes it much easier to generalize. Or of course R.flip(R.contains). Regardless, the flip(difference) answer seems cleaner anyway.
0

With vanilla JavaScript, you can make a copy of each of your two arrays, with .map() returning a string representation of your array elements.

Then loop over your removable items array and check with indexOf() over the existence of each item in your copied array.

This is how should be your code:

var arr = [["g", "d"], [5, 11], [1, 2], [43, 4], ["a", "b"]];
var strArr = arr.map(function(a){
    return a.join(",");
});
 var toRemove = [[1, 2], ["a", "b"]];
 var strToRemove = toRemove.map(function(el){
    return el.join(",");
 });

strToRemove.forEach(function(a){
    if(strArr.indexOf(a)>-1){
        arr.splice(strArr.indexOf(a), 1);
        strArr.splice(strArr.indexOf(a), 1);
    }
});

Demo:

var arr = [
  ["g", "d"],
  [5, 11],
  [1, 2],
  [43, 4],
  ["a", "b"]
];
var strArr = arr.map(function(a) {
  return a.join(",");
});
var toRemove = [
  [1, 2],
  ["a", "b"]
];
var strToRemove = toRemove.map(function(el) {
  return el.join(",");
});

strToRemove.forEach(function(a) {
  if (strArr.indexOf(a) > -1) {
    arr.splice(strArr.indexOf(a), 1);
    strArr.splice(strArr.indexOf(a), 1);
  }
});
console.log(arr);

6 Comments

There are several problems with this. First of all, why would you remove the test string when it's found? (I suppose one could imagine trying to remove only the first instance of the items, but that seems less likely.) Second, if itemsToRemove contained ["43,4"], for instance, this would remove [43, 4]. Maybe that's not a concern for the expected data, but it makes it harder to generalize. The other two answers don't share this problem.
@ScottSauyet We remove the string, so the indexes will be updated in both arrays, otherwise, we will be removing wrong items, for the [43, 4] thing, we could fix it, the purpose of my answer, is to use only vanilla JS to do it.
While it's perfectly legitimate to show a way to do something in vanilla JS even when the question specifically asked about using a library, you do have to note that the two answers using the library both involve cleaner code, and they cover many more cases, such as ["43,4"] or not removing [{a:1}, {b:2}] when the search list has [{a:1}, {b:3}]. toString can be a very blunt instrument.
@ScottSauyet *well you are right about that, it's a delicate situation and using a string for comparison may lead to some problems, but I gave this quick solution so it fits the OP requirements as they are :)
True enough, and it does meet the example given. (I should note that I'm one of the authors of Ramda.) To me, this discussion shows some of the advantages of a library. But of course I cannot deny that there are many reasons to avoid libraries as well.
|
0

Just use following lines of code:

const data = [
  ['g', 'd'],
  [5, 11],
  [1, 2],
  [43, 4],
  ['a', 'b']
]
const itemsToRemove = [
  [1, 2],
  ['a', 'b']
];

console.log(R.difference(data, itemsToRemove));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.