开发者

Filter n arrays by excluding values that don't exist in each

I have n arrays with which I need to determine if x is in all of the n arrays. (where n is any number, and x is a numeric value) I have something like the following in place, but it's always ending up false.

function filterArrays()
{
  var x = $(this).attr('id'); // ex: 2
  var arrays = [[1,2,3],[2,4,6]];
  var result = false;
  for each (var n in arrays)
  {
    result = result ^ (n.indexOf(x) > -1);
  }
}

How do I make result equal to true when x is in both arrays, but when x is not in both arrays, make result equal to false?

The function above will be used with jQuery's filter() method. Example:

$(arrayOfElementsWithNumericIds).filter(arrayFilter);
// arrayOfElementsWithNumericIds prototype: [div#1,div#2,div#3,...]

I'm th开发者_StackOverflow社区inking that a bitwise operation is called for, but I could be wrong. Please explain why your solution is right and why mine isn't working. (for bonus points)


Here are some issues with your example:

  • Comparing number to string (id is a string). Use x = parseInt(...)
  • Using the ^ operator. Instead initialize result to true and use &&.
  • Get rid of each. The correct syntax is for (key in object)

I've modified your code as little as possible:

function filterArrays()
{
    var x = parseInt($(this).attr('id')); // ex: 2
    var arrays = [[1,2,3],[2,4,6]];
    var result = true;
    for (var n in arrays)
    {
        result = result && (arrays[n].indexOf(x) > -1);
    }
    return result;
}

That being said, you can really optimize your code by using Array.every() and Array.some(). Also, using $(this).attr('id') creates a jQuery object unnecessarily since you can just say this.id directly.

function filterArrays()
{
    var x = parseInt(this.id); // ex: 2
    var arrays = [[1,2,3],[2,4,6]];
    var result = arrays.every(function(array)
    {
        return array.some(function(item)
        {
            return item === x;
        });
    });
    return result;
}


I think that you are looking for this:

  var result = true;
 for each (var n in arrays)
  {
    result = result && (n.indexOf(x) > -1);
  }

That is, assume that the value is in all the arrays to start. Then using the AND (&&) operator you get

  true AND (value is in current array)

if at any time the value is not in an array it becomes false and the entire operation will be false. Otherwise it remains true until the end of the loop.


xor's not the way to go. Look at it this way:

search for 2, start  result = false
1st array: 2 is present, result = false xor true = true
2nd array: 2 is present, result = true xor true = false
end: result is false (WRONG)

search for 4, start result = false
1st array: 4 is present, result = false xor true = true
2nd array: 4 is  absent, result = true xor false = true
end: result is true (WRONG)

You want a cummulative bit-wise and.

start: result = true, search for 2
1st array: 2 is present, result = true and true = true
2nd array: 2 is present, result = true and true = true
end: result is true (RIGHT)

start: result = true, search for 4
1st array: 4 is present, result = true and true = true
2nd array: 4 is absent, result = true and false = false
end: result if false (RIGHT)


Why Don't you extend the array prototype with a contains method? that way you can loop over each array and or/and the current result with the previous one.


You can loop over your 'arrays' object if you want, but, I think you just want a Set Intersect operation. This is one way to do it in jQuery, and it won't care about if the attr(id) value of x is an integer or string. I'm on lunch, i'll test this in a page quick...

function filterArrays(){
  var x = $(this).attr("id");
  var arrays = [[1,2,3],[2,4,6]];
  var result = ($.inArray(arrays[0], x )>0 && $.inArray(arrays[1], x) >0);
  return result;
}


Using http://phrogz.net/JS/ArraySetMath.js you could:

var sets  = [[1,2,3],[2,3,7],[1,7,2]];
var isect = sets[0];
for (var i=1,len=sets.length;i<len;++i){
  isect = isect.intersection( sets[i] );
}
console.log( isect );
// [2]

Or, using JS.Set you could:

var sets  = [[1,2,3],[2,3,7],[1,7,2]];

// Or JS.HashSet or JS.Set
var isect = new JS.SortedSet(sets[0]);
for (var i=1,len=sets.length;i<len;++i){
  isect = isect.intersection( new JS.SortedSet(sets[i]) );
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜