3

How do I specify multiple index values of an array without iterating through all of them?

I have an array: var boxArray = $(’.box’).toArray();. I have 9 elements with the class box, so this array is comprised of the index values [0, 1, 2, 3, 4, 5, 6, 7, 8].

If boxArray index values of [0], [4], and [8] are all given a class of clicked, I want something to happen. I know I can use a for loop to iterate through the entire array, and I know I can reference just one index value (boxArray[0]), but how would I denote multiple out-of-order index values at once?

$(boxArray[0, 4, 8]) doesn’t work - only the last index value is recognized. $(boxArray[0][4][8]) doesn’t work

Is the only way to do this in JavaScript and jQuery to reference them one at a time? Ideally I'd like to be able to do something like this:

if ($(boxArray[0, 4, 8]).hasClass(‘clicked’)) {
  // do something;
}

instead of

if ($(boxArray[0]).hasClass('clicked') &&
    $(boxArray[4]).hasClass('clicked') &&
    $(boxArray[8]).hasClass('clicked')
) {
  // do something
}
5
  • is is possible to provide the fiddle for this ? Commented Feb 27, 2017 at 13:38
  • 5
    what's the problem with iterating over them? Commented Feb 27, 2017 at 13:40
  • I added more code up there instead of a jsfiddle. My issue with the for-loop is that I have eight total combinations of three index values which I need to reference, several of which are out of order. I'm just hoping there's a magical non for-loop way to access multiple out of order index values. Commented Feb 27, 2017 at 13:43
  • 1
    Why exactly 0, 4 and 8? What do they have in commun? Can they be selected by something? Commented Feb 27, 2017 at 13:47
  • 3
    Is this about TicTacToe? Because there are easier ways to check for three in a row. Commented Feb 27, 2017 at 13:49

5 Answers 5

2

You can use Array.prototype.every():

The every() method tests whether all elements in the array pass the test implemented by the provided function.

The snippet:

var boxArray = $('.box').toArray();

var result = [1, 2, 4].every(function(element, index, array) {
    return boxArray[element].classList.contains('clicked');
});
console.log(result);

result = [0, 2, 4].every(function(element, index, array) {
    return boxArray[element].classList.contains('clicked');
});
console.log(result);

//

if ([0, 2, 4].every( (ele) => {return $(ele).has('.clicked');})) {
    console.log('test passed');
} else {
    console.log('test not passed');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>



<button class="box clicked">box</button>
<button class="box">box</button>
<button class="box clicked">box</button>
<button class="box">box</button>
<button class="box clicked">box</button>
<button class="box">box</button>
<button class="box">box</button>
<button class="box">box</button>

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

Comments

1

You can make a function that do the check for you (using the arguments object). Like this:

function check(arr) {
    for(var i = 1; i < arguments.length; i++) {          // for each index (arguments after the first which is the array)
        if( ! $(arr[arguments[i]]).hasClass('clicked') ) // if one of them doesn't have the class 'clicked' then return false
            return false;
    }
    return true;                                         // if all have the class clicked then return true
}

And then you can call it like this:

if(check(boxArray, 0, 4, 8)) {
    // boxArray[0], boxArray[4] and boxArray[8] have the class clicked
}
// or
if(check(boxArray, 0, 4, 8, 3, 1, 7, 11)) {
    // all the .box elements at indexes 0, 4, 8, 3, 1, 7 and 11 have the class 'clicked'
}
// ...

Note: If you pass only the array as parametter (check(boxArray)), then the returned value will be true. If you want to return false in this case then just put this line as the first line of the function check:

if(arguments.length <= 1) return false;

Comments

1

You can use map() method or filter() method, or every method (like @gaetanoM's answer):

For using map:

var boxArray = []; 

$('.box').toArray().map((x, y, z) => {
  if (y === 0 || y === 4 || y === 8) boxArray.push($(x));
});

boxArray.forEach(box => {
  if (box.hasClass('clicked')) {
    // do something...
  }
});

For using filter:

var boxArray = $('.box').toArray().filter((x, y, z) => {
  if (y === 0 || y === 4 || y === 8) return $(x);
});

boxArray.forEach(box => {
  if (box.hasClass('clicked')) {
    // do something...
  }
});

10 Comments

It's not the usecase of map. It's more of forEach or filter!
@ibrahimmahrir I've refered the doc in the answer.
map is used to return an array out of the input array => so it's just a waste of ressources and should not be used just to loop an array, that's the usecase of forEach.
filter will be even clearer if you write the code like this: var boxArray = $('.box').toArray().filter((x, y) => y === 0 || y === 4 || y === 8);
so it's just a waste of ressources and should not be used just to loop an array. Can you give a document said that? MDN document doesn't mention about that.
|
1

you can use jquery.fn.filter(function) please.then you can check filter(..).length==[2,8].length

$('button').click(function(){
  var selectors=[2,8];
  
  $('.box').filter(function(index,element){
    return selectors.indexOf(index)!=-1&&$(element).has('.checked');
  }).addClass('active');
});
.box{
 float:left;
 border:1px solid #000;
 width:80px;
 height:50px;
 margin:5px;
}
.active{
 color:red;
}
button{
clear:both;
display:block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>filter [2,8] without 4</button>
<div class='box'>.box</div>
<div class='box'>.box</div>
<div class='box checked'>.box .checked</div>
<div class='box'>.box</div>
<div class='box checked'>.box .checked</div>
<div class='box'>.box</div>
<div class='box'>.box</div>
<div class='box'>.box</div>
<div class='box checked'>.box .checked</div>
<div class='box'>.box</div>

Comments

0

Shortest way to do this would be

if ($(boxArray[0], boxArray[4], boxArray[8]).hasClass("clicked")) {
  // do something;
}

1 Comment

In my program, your solution only seems to work on the first index value (boxArray[0]), having no effect on the next two. Maybe it's my specific code, but are you sure on the comma separation with the jQuery? I'm wanting it to make sure all of those three index values have the 'clicked' class. Apologies - next time I'll post a fiddle for everyone.

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.