1

I'm trying to discover a more concise way of finding the indexes in an array that match a condition and then push them into an array. I've made some attempts but either doesn't return the answer I want or are much too verbose.

Could someone shed some ES6 light here as to what the best way of doing this is? thanks for any help

var arr = ["00", "000", "", "0", "000"],
  p = [];
var l = (arr.reduce((a, b) => a.length > b.length ? a : b)).length;

arr.filter(c => c.length === l); // returns ["000", "000"]
arr.map(c => c.length === l); // returns [false, true, false, false, true]
arr.map((c, i) => c.length === l ? i : c); // returns ["00", 1, "", "0", 4]
// arr.findIndex(return c.length === l) // error
function longestInstances(el) {
  return el.length == l
} // returns 1 only (after console logged)
console.log(arr.findIndex(longestInstances));
for (i = 0; i < arr.length; i++) {
  // works but verbose
  if (arr[i].length == l) {

    p.push(i);

  }

  console.log('p: ' + p);
}

5
  • 2
    please add the condition and the wanted result as well. Commented Jul 25, 2018 at 8:57
  • Don't know exactly which are your conditions, but Array.prototype.find is probably what you're looking for. Commented Jul 25, 2018 at 8:57
  • @Zim - Not if the OP wants indexes instead of values, and not if they want indexes plural. Commented Jul 25, 2018 at 8:58
  • 1
    @T.J. Crowder - right, my mistake! Commented Jul 25, 2018 at 9:01
  • sorry, can't believe i didnt specify the condition! Yes, the indexes in arr where the longest strings occur Commented Jul 25, 2018 at 10:08

3 Answers 3

3

My understanding is you want to find the indexes in arr where the longest strings occur, having already found the longest string length l.

A simple loop seems the most direct, perhaps using forEach (or of course, just a for loop as in the question):

var indexes = [];
arr.forEach((s,i) => {
  if (s.length === l) {
    indexes.push(i);
  }
});

Live Example:

var arr = ["00", "000", "", "0", "000"], p=[];
var l = (arr.reduce((a,b)=>a.length>b.length?a:b)).length;
var indexes = [];
arr.forEach((s,i) => {
  if (s.length === l) {
    indexes.push(i);
  }
});
console.log(indexes);

You can shoehorn that into a reduce if you like (you can shoehorn anything into reduce, and people seem to like to do that), but you don't gain anything by it.

There are also all sorts of other ways you can complicate it, like creating an array of objects with both the original value and its original index, filtering that, and then converting to just indexes:

var indexes = arr
  .map((string, index) => ({string, index}))
  .filter(e => e.string.length === l)
  .map(({index}) => index);

Live Example:

var arr = ["00", "000", "", "0", "000"], p=[];
var l = (arr.reduce((a,b)=>a.length>b.length?a:b)).length;
var indexes = arr
  .map((string, index) => ({string, index}))
  .filter(e => e.string.length === l)
  .map(({index}) => index);
console.log(indexes);

That avoids explicit ifs and does the work in a more streaming, functional-style way, but does involve multiple passes through the array. But OliverRadini shows a better way of doing something similar, though it still involves multiple passes where the simple approach takes just one.

So again, barring some specific reason for preferring a streaming approach like that, the simple loop is the direct, simple, fast approach.

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

Comments

2

Matching Condition

This answer presumes that you're looking to get the indices of the elements which are of equal length to the element in the array with the maximum length.


Getting the Indices

To get the length of the longest element, we first get the lengths of each element, then reduce the array so as to get only the maximum length.

Next, we map each element of the array to one of two things; if the element is the same length as the maximum length, we take its index. If it isn't, then we map false instead. We do that so we can filter out those values.

Lastly, we filter out values which are false. These values were not as long as the maximum length, so we don't want them.


As T.J.Crowder alluded to, a forEach might do this in a way that's more direct, and potentially more readable. Experimenting with chaining array methods in this way will allow you to make a good decision as to the kind of code which will work best for the situation with which you are faced.

If you are working with very large data sets, then iterating over your data multiple times in order to improve code readability, at the expense of performance, is probably a bad idea.

const arr = ["00", "000", "", "0", "000"]

const maxLength = arr
  .map(e => e.length)
  .reduce((a, b) => a > b ? a : b)
  
const result = arr
  .map((val, i) => val.length === maxLength ? i : false) // log the index of the item if the item's length is 1
  .filter(i => i !== false) // remove non-truthy elements
  
console.dir(result)

1 Comment

I've now updated my code to be in line with the same presumed matching condition used in other answers. Also updated the filter function, thanks for the input
0

You could reduce the array by taking the indices which match the length condition.

var array = ["00", "000", "", "0", "000"],
    indices = array.reduce((r, s, i, a) => {
        if (!r || s.length > a[r[0]].length) { // check initial or greater length
            return [i];
        }
        if (s.length === a[r[0]].length) {     // check same length
            r.push(i);
        }
        return r;
    }, undefined);
    
console.log(indices); // [1, 4]

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.