Is there a way to get the index of the filtered array while filtering

I have a variable, idx, that controls the current index of an array of elements called items. While running a filter on this array, I want to change idx to current index of the filtered array if it matches a condition. Basically, I want the index to point to the same data before and after the filter.

This a simplified version of a webapp where users are shown lists of items and they can "pin" specific items so that every remaining list also contains that pinned item. Pinning an item sets the filter to that item. Only one list is shown at a time which is what idx represents.

let items = [
  [{/**/}, [1, 2, 3]],
  [{/**/}, [2, 2, 2]],
  [{/**/}, [3, 6, 0]],
  [{/**/}, [4, 7, 3]],
  [{/**/}, [5, 4, 9]],
  [{/**/}, [7, 1, 8]],
  [{/**/}, [8, 4, 4]],
  [{/**/}, [0, 7, 1]]
]

let idx = 5; //Current index
let curr = items[idx][1]; // Assume this is always up to date [7, 1, 8]
let filter = 1; // Data we want to filter for

// Filter items that contain the number 1
let filtered = items.filter(function(item) {
    if (!item[1].includes(filter))
        return false;
    if (item[1] == curr)
        idx = INDEX_IN_FILTERED_ARRAY(would be 1 in this case);
    return true;
});

2 thoughts on “Is there a way to get the index of the filtered array while filtering”

  1. You could keep track in your filter callback, since you know that you’ll get a call for every element of the original array and you know whether you’ve returned true or false for each element:

    let indexInNewArray = 0;
    let filtered = items.filter(function(item) {
        if (!item[1].includes(filter))
            return false;
        ++indexInNewArray; // Since we know we're adding to it
        if (item[1] == curr)
            idx = indexInNewArray;
        return true;
    });
    

    But note that idx will get overwritten each time you keep an entry, so you’ll only know the index of the last entry that was kept, which you know anyway: It’s filtered.length - 1.


    Side note: Your sample data has numbers, not strings, in the first element of each of the subarrays, but you’re using includes on it. includes is a string or array method, but not a method on numbers.

    Reply
  2. I ended up using James’ findIndex answer

    $: idx = filtered ? (index => index >= 0 ? index : 0)(filtered.findIndex((item) => item[1].every((num, index) => num === $pinned[index]))) : 0;
    
    Reply

Leave a Comment