15

Is there a way to select multiple array elements at once?

I have this code:

var my_array = ["a", "b", "c", "d", "e", "f"];

I would like to select 1st, 3rd, 5th, 7th, 9th element from the array at the same time, something like this

my_array[0,2,4,6,8];
3
  • 1
    You're going to have to loop or individually assign them. Subscripts don't work that way Commented Sep 17, 2016 at 14:15
  • In this particular case you may want to look at the n-th-child css selector Commented Sep 17, 2016 at 14:18
  • That's not an array BTW. Commented Sep 17, 2016 at 14:37

8 Answers 8

26

The easiest way to achieve this nowadays is to use the map function:

[0,2,4,6,8].map(x=>my_array[x]);

The trick is to call the map function on an array of the desired indexes. An array map function will return an array of the same length as the array it is called on. The callback function inside the map function (x=>my_array[x]) then returns the value of my_array for each of the desired indexes.

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

2 Comments

can also add .filter(x=> x !== undefined) to remove undefined elements .. so something like this [0,2,4,6,8].map(x=>my_array[x]).filter(x=> x !== undefined)
that's such an awkward solution compared to simple multi indexing :D
3

The easiest way, if you must use JavaScript, would be to set up a simple function, to which you pass the array and the indices:

function modifyStylesOf(arr, indices, prop, newValue) {

    // here we filter the array to retain only those array elements
    // are present in the supplied 'indices' array:
    arr.filter(function(el, index) {

      // if the index of the current element is present in the
      // array of indices the index will be zero or greater,
      // so those elements will be retained (as the assessment
      // will be true/truthy:
      return indices.indexOf(index) !== -1;

    // we iterate over the retained Array elements using
    // Array.prototype.forEach():
    }).forEach(function (el) {

      // and here we update the passed-in property
      // to the passed-in value:
      el.style[prop] = newValue;
    });
}

Then call with:

// here we use Array.from() to convert the nodeList/HTMLCollection
// into an Array:
modifyStylesOf(Array.from(c), [1,3,5,7,9], 'webkitTextFillColor', 'transparent');

function modifyStylesOf(arr, indices, prop, newValue) {
  arr.filter(function(el, index) {
    return indices.indexOf(index) !== -1;
  }).forEach(function(el) {
    el.style[prop] = newValue;
  });
}

var c = document.querySelectorAll('body div');

modifyStylesOf(Array.from(c), [1, 3, 5, 7, 9], 'webkitTextFillColor', 'orange');
div {
  counter-increment: divCount;
}
div::before {
  content: counter(divCount, decimal-leading-zero);
}
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>

Bear in mind, though, that your original selector included all childNodes (which necessarily includes textNodes, and HTML comment nodes (among, potentially, others); whereas it seems you want only HTMLElements; for that I'd strongly suggest using a slightly different means of selection:

// the Element.children property will retrieve only
// element nodes:
var c = document.getElementById("nc-2").children;

Or:

// using document.querySelectorAll(), with a CSS
// selector can select only elements (as with CSS),
// though I'd suggest something more specific than
// the universal selector ('*') to specify which
// child elements to select:
var c = document.querySelectorAll('#nc-2 > *');

Further, though without seeing your HTML it's rather hard to be particularly precise, it seems that you're trying to select only the odd-numbered indices of the childNodes, which lends itself to using CSS only to achieve your goal. In your specific case that would be:

#nc-2 > :nth-child(odd) {
  -webkit-text-fill-color: transparent;
}

body > div:nth-child(odd) {
  -webkit-text-fill-color: orange;
}

div {
  counter-increment: divCount;
}

div::before {
  content: counter(divCount, decimal-leading-zero);
}
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>
<div></div>

3 Comments

...or eventually using CSS and #nc-2 *:htn-child(odd)
@Roko: yeah, it took me longer than anticipated to run through and verify the function, create the demo and then point out the issues with using childNodes versuse children...CSS added (finally)! :)
Thanks man ,work's perfectly,this is the first answer that I tested and work's just as I wanted so I won't look at the other answers but thanks a lot Dashing Dev,Oscar Gomez Alcaniz,Explosion Pills.
2

var myArray = ["a", "b", "c", "d", "e", "f"];
var myIndices = [0, 2, 4, 6, 8];

var result = [];
myIndices.forEach(i => result.push(myArray[i]));

console.log(result);

(undefined because some of these indices are off the end of the data).

1 Comment

If the array and indices are large, is it more efficient to create the result array with a defined length?
0

This is where something like jQuery can actually come in handy because it can operate on collections:

$("#nc-2").children(":odd").css("-webkit-text-fill-color", "transparent");

You can do this without jQuery of course, but you have to loop yourself.

document.querySelectorAll("#nc-2 > :nth-child(odd)").forEach(
  elem => elem.style.WebkitTextFillColor = "transparent"
);

document.querySelectorAll("#nc-2 > :nth-child(odd)").forEach(elem => elem.style.backgroundColor = "purple")
div > div {
  background-color: blue;
  width: 50px;
  height: 50px;
  margin: 5px;
  display: inline-block;
}
<div id="nc-2">
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
  <div></div>
</div>

Comments

0

In Javascript, you can loop through the code like this below:

var c = document.getElementById("nc-2").childNodes;
for(var count=0; count < c.length; c++){
  //this condition is used to test for odd indexes
  if(count%2 !== 0){      
    c[count].style.webkitTextFillColor="transparent"; 
  }
}

Comments

0

You can try with a good old forEach:

document.getElementById("nc-2").childNodes.forEach(function (node, index) {
  if ([1,3,5,7,9].indexOf(index) >= 0) { node.style.webkitTextFillColor="transparent"; }
});

Comments

0

After you convert your Node List into an array like var childNodes = [...nodeList] then the rest is like this;

var childNodes = ["child0","child1","child2","child3","child4","child5","child6","child7","child8","child9"],
 selectedNodes = childNodes.reduce((p,c,i) => i & 1 ? p.concat(c) : p,[]);
console.log(selectedNodes);

Note: i & 1 is true when i is odd.

Comments

0

or the filter function

const indexes = [0,2,4,6,8];
    
my_array.filter((v,i)=>indexes.includes(indexes));

although this is O(n*m) so the map function from @tommyleejones is faster since that doesn't have to compare values but rather uses indexes to its only O(n)

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.