2

I'm fairly new to JavaScript and could need some help with a problem I'm facing while working on a Google Apps Script.

What I'm intending to do is to filter my data based on an array, which I grab from a specific cell in a specific sheet, that contains string elements I don't want to keep in my data. In other words, rows that include these keywords should be removed from my sheet.

Thus far I have managed to do this using a single string element in my filter function.

// elements to filter out.
var keys = [['a','b','c']];

// example data.
var data = [['a',1,2],
            ['c',4,3],
            ['d',3,4]];

// my approach for a single element which works.
var filterText = "a";
var newData1 = data.filter(function(item) {
  return item[0] !== filterText;
});
console.log(newData1); // output: [ [ 'c', 4, 3 ], [ 'd', 3, 4 ] ]

However, if I try to extend this logic to the case were I'm using an array to filter my data, I'm in trouble. I wrote the code below which correctly checks my data but does not return the expected outcome. I know I'm missing out on a crucial part of code here but can't figure out which one it is. I turned the code around several times but got stuck either way.

for(var n=0; n<keys[0].length; n++) {
  // console.log(keys[0][n]);
  var newData2 = data.filter(function(item) {
    // console.log(item[0] === keys[0][n]);
     return item[0] === keys[0][n];
  })
};
console.log(newData2); // output: [ [ 'c', 4, 3 ] ]

Hope you guys could point me in the right direction and help me to understand where I'm making my mistake here.

Thanks!

5 Answers 5

2

I'd make an object with all your unwanted keys, then I'd use them to filter your data array.

const ObjectOfKeys = keys.reduce((acc,rec)=> {
                        let nextAcc = acc;
                        nextAcc[rec] = true;
                        return nextAcc;
                        },{}};

const filteredData = data.filter(rec => !ObjectKeys[rec[0]])

alternatively approach, you could skip making the object if your keys were unique.

const filterData = data.filter(rec => !keys.includes(rec)) Note. this will not work if for example your key is 'apple' and data[0] is 'a', so first approach would ensure no such conditions throw the code off.

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

7 Comments

I'd to learn how to use this method and I'm wondering if this return nextAcc;},{}}; should be this return nextAcc;},{});
Also I think that this line const filteredData = data.filter(rec => !ObjectKeys[rec[0]]) should be this way const filteredData = data.filter(rec => !ObjectOfKeys[rec[0]])
That's pretty cool. Actually I never even noticed that we only had to test the first column.
How do you know thatacc is an object?
last line of the reduce function is "},{})", that's where you ask for Object or Array ( "}, [ ] }") to be returned. acc -> the accumulator will take the shape of what you define as the return type. (I'm not following your 1st 2 comments listed above, if they're still valid, please elaborate)
|
1

Try this:

function myfunction() {
  var keys = [['a','b','c']][0];//flatten
  var data = [['a',1,2],['c',4,3],['d',3,4]];
  var d=0;
  for(var i=0;i-d<data.length;i++) {
    for(var j=0;j<data[i-d].length;j++) {
      if(keys.indexOf(data[i-d][j])!=-1) {
        data.splice(i-d++,1);//remove the row and increment the delete counter
        break;//break out of inner loop since row is deleted
      }
    }
  }
  console.log(data);
}

Thanks for the other solutions. I really need more practice with other array methods and arrow notation. Just for kicks I increased the dataset size to 1200 lines and ran the different methods side by side and below is a csv of the data. Not really conclusive. It was the same data set each time and I used console.log output on all of them. The data came from the view executions output.

Cooper,1.171
Cooper,1.195
Farnoosh,1.2
Farnoosh,1.224
Cooper,1.237
TheMaster,1.257
Cooper,1.264
Farnoosh,1.347
TheMaster,1.371
TheMaster,1.392
Cooper,1.503
Farnoosh,1.513
Farnoosh,1.563
TheMaster,1.699
TheMaster,1.936

Comments

1

Create a Set of the keys and use set.has:

// elements to filter out.
const keys = [['a','b','c']],
keySet = new Set(keys[0]),

// example data.
data = [['a',1,2],
        ['c',4,3],
        ['d',3,4]],
out = data.filter(([item0])=>!keySet.has(item0));
console.info(out);

1 Comment

That’s an interesting idea.
0
// elements to filter out.
var keys = [['a','b','c']];

// example data.
var data = [['a',1,2],
            ['c',4,3],
            ['d',3,4]];

// my approach for a single element which works.

var newData1 = data.filter(function(item) {
if (keys.indexOf(item[0]) != -1) {return item}
});
console.log(newData1); // output: [ [ 'c', 4, 3 ], [ 'd', 3, 4 ] ]

1 Comment

Please don't post only code as answer, but also provide an explanation what your code does and how it solves the problem of the question. Answers with an explanation are usually more helpful and of better quality, and are more likely to attract upvotes.
0

This solution works for me:

// elements to filter out.
var keys = [['a','b','c']];

// example data.
var data = [['a',1,2],
        ['c',4,3],
        ['d',3,4]];

//filtrated data 
var newdata = data.filter(item => keys.find(p => p[0] === item[0]))

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.