12

I have an array of people's names along with their knowledge of languages. What I want to do is pass a filter onto the language column and filter out any results that don't match.

This is the sample array

   var myArray = [["Steppen", "Spanish Polish"],
                  ["Wolf", "Spanish Polish Tagalog"],
                  ["Amanda", "Spanish"],
                  ["Ada", "Polish"],
                  ["Rhonda", "Spanish Tagalog"]];

As far as passing in filters, it could be either one language or many. Even if one language from a filter matches - the result should be returned. So for example, a filter of "Tagalog" should return - Wolf and Rhonda. A filter of "Spanish Polish" should return everyone - there's either a match in Spanish or Polish.

I wrote the filter function but for some reason it's getting stuck, when I pass the filter "Tagalog" it only iterates to the second cell in the array (Spanish Polish Tagalog) and repeats itself multiple times instead of going forward.

What am I doing wrong, should I be iterating differently?

 var userPassedFilter = new Array();
 userPassedFilter[0] = "Tagalog";

 newArray = consolidatedFilters(myArray, userPassedFilter);
 console.log(newArray);

 function consolidatedFilters(passedArray, passedFilter)
 {
 var filteredArray = passedArray.filter(    
    function(el)
    {
        for (var i = 0; i < passedArray.length; i++)
         {
            console.log("i is " + i);
             for (var j in passedFilter)
            {
                console.log("Passed Filter j " + passedFilter[j]);
                console.log("Passed Array  i " + passedArray[i][1]);        
                console.log("String Search " + passedArray[i][1].search(passedFilter[j]));

                if (passedArray[i][1].search(passedFilter[j]) != -1)
                {
                    return true;
                }
            }           
        }
         return false;
    }
 );     
 return filteredArray;
 }
5
  • you should look into using jQuery.each() api.jquery.com/jQuery.each Commented Sep 8, 2011 at 20:17
  • Are you using jQuery's .filter or the native array's .filter? It looks like passedArray is the array you described, which is not a jQuery object. Commented Sep 8, 2011 at 20:18
  • I'm using jQuery's .filter(function) to return the array that I want based on the passedFilter. passedArray is just the sample array I described above. Commented Sep 8, 2011 at 20:21
  • @firedrawndagger: I'm not sure I understand. If passedArray is that array, then passedArray.filter is not the jQuery version at all. It's the built-in .filter. [...].filter is the native one, $(...).filter is the jQuery one. Commented Sep 8, 2011 at 20:22
  • @pimvdb you're right, I totally confused that. It is is the native JavaScript filter. Commented Sep 8, 2011 at 20:26

5 Answers 5

23

this is the ultimate solution in the ES6 way: No need to Search the same query again in another thread.

var array1 = ['a', 'b', 'c', 'd', 'e'];
var array2 = ['b', 'd', 'f'];

array1 = array1.filter(function(item) {
  return !array2.includes(item); 
})
console.log(array1); // [ 'a', 'c', 'e' ]
console.log(array2); // [ 'b', 'd', 'f' ]

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

2 Comments

This should be the selected answer as is both concise and efficient.
Is there the same efficient way if the array consists of objects? My current approach is arr1.filter((x) => !arr2.some((y) => x.value === y.value)
14

To me it seems like you're making it a little too complicated.

  1. Iterating three times (filter, for loop, for in loop).
  2. Using a for in loop for an array.
  3. Using both new Array and [...].

I updated it a little and it looks like this is what you want: http://jsfiddle.net/pimvdb/RQ6an/.

var myArray = [["Steppen", "Spanish Polish"],
              ["Wolf", "Spanish Polish Tagalog"],
              ["Amanda", "Spanish"],
              ["Ada", "Polish"],
              ["Rhonda", "Spanish Tagalog"]];

var userPassedFilter = ["Tagalog"];

newArray = consolidatedFilters(myArray, userPassedFilter);
console.log(newArray);

function consolidatedFilters(passedArray, passedFilter) {
    var filteredArray = passedArray.filter(
    function(el) { // executed for each person
        for (var i = 0; i < passedFilter.length; i++) { // iterate over filter
            if (el[1].indexOf(passedFilter[i]) != -1) {
                return true; // if this person knows this language
            }
        }
        return false;
    }
    );     
    return filteredArray;
}

1 Comment

While I agree with this solution, but this seems like O(n^2) if I am not wrong. stackoverflow.com/questions/26446055/run-time-of-nested-loops Is there any other efficient way ? Thanks
3

here is a more generic version that removes all elements that are in the filter array

function destroyer(arr) {
  // Remove all the values
  var passedArray = arr;
  var passedFilter = Array.prototype.slice.call(arguments, 1);

  var newArray = passedArray.filter(function(x){
    if(passedFilter.indexOf(x) !== -1){
      return false;
    }
    return true;
  });

  return newArray;
}


destroyer([1, 2, 3, 1, 2, 3], 3, 2);
//prints [1,1]

1 Comment

it looks like you too found this post while searching around during the Free Code Camp "Seek and Destroy" challenge. I've been struggling with that particular challenge, and your input here helped my understanding of some js logic.
2

I'm new to javascript and this is the only way I was able to filter an array with another array which made sense to me:

function filterThisByThis(arr) {
var numArgs = arguments.length; 
var newArr = [];
for (var i = 1; i < numArgs; i ++) {
newArr.push(arguments[i]); 
} // makes a new array from all arguments parsed to fuction minus the orginal array 
arr = arr.filter(function(val) {
  for (var j = 0; j < newArr.length; j++) {
   if (val == newArr[j]) {
      return false;}
  }
  return true;
  }); // uses the filter function to iterate over the orginal array taking out all values which occur in the new array 
return arr;
}  
filterThisByThis([1, 2, 3, 4, 1, 2, 3, 4], 1, 3);
// prints [2, 4, 2, 4]

Comments

1

Another answer to @millerjay response

function destroyer(arr) {
    var array = arr;
    var filterArray = Array.from(arguments).slice(1);
    var filtered = arr.filter(function(val){
        return filterArray.indexOf(val) === -1;
    });
    return filtered;
}

destroyer([1, 2, 3, 1, 2, 3], 3, 2);
//prints [1,1]

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.