Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how can I filter an array without losing the index?

I have two really long arrays containing "picture names" and "picture files". The first one represents the actual name of the pictures, while the second one is just the file name. For example:

picturenames[0] = '0 - zero';
picturenames[1] = '1 - one';
picturenames[2] = '1 o\'clock';
...
picturefiles[0] = 'numbers-zero.jpg';
picturefiles[1] = 'numbers-one.jpg';
picturefiles[2] = 'time-1.jpg';
...

I have about 1000 items in each array in several languages (the picture files are always the same). I'm "recycling" these arrays from the previous application to save some time and avoid rewriting everything anew.

Desirable functionality: using the user's input in a textbox I want to filter the picturenames array and then show the correspondant picturefiles image.

The issue I'm facing: when I filter the picturenames array I lose the index and I can't "reach" the picture file name.

This is the code I'm using to filter the picturenames array.

var matches = picturenames.filter(function(windowValue){
    if(windowValue) {
        return windowValue.indexOf(textToFindLower) >= 0;
    }
});

What would be the best way to do this?

UPDATE: the solution proposed by Ahmed is the best one, but for time reasons and negligible performance issues I'm just using a for loop to search trough the array, as follows:

        var matchesCounter = new Array();

        for (i = 0; i < picturenames.length; i++) {
            if (picturenames[i].indexOf(textToFindLower) >= 0) {
                matchesCounter.push(i);
            }
        }

        console.log(matchesCounter);

        for (i = 0; i < matchesCounter.length; i++) {
            console.log(picturenames[i]);
            console.log(picturefiles[i]);
        }
like image 350
devamat Avatar asked Mar 26 '18 02:03

devamat


Video Answer


2 Answers

Try this:

const foundIndicies = Object.keys(picturenames).filter(pictureName => {
  pictureName.includes(textToFindLower)
});
// reference picturefiles[foundIndicies[0]] to get the file name

Though, it would be far nicer to have both the name and the file in a single object, like so:

const pictures = [
  {
    name: '0 - zero',
    file: 'numbers-zero.jpg',
  },
  {
    name: '1 - one',
    file: 'numbers-one.jpg',
  }
];

const foundPictures = pictures.filter(picture => picture.name.includes('zero'));
if (foundPictures[0]) console.log(foundPictures[0].file);
like image 95
CertainPerformance Avatar answered Sep 18 '22 08:09

CertainPerformance


You can add one property index during the filtering time, then later on you can use the index.

var matches = picturenames.filter(function(windowValue, index){

if(windowValue) {
    windowValue.index = index;
    return windowValue.comparator(textToFindLower) >= 0;// Need to define comparator function
}
});

Later on you can access by using like follows:

picturefiles[matches[0].index]

However, the solution will work on object, not primitive type string.

If your data type is string, then you have to convert as object and put the string as a property value like name. The snippet is given below:

var picturenames = [];
var picturefiles = [];

picturenames.push({name:'0 - zero'});
picturenames.push({name:'1 - one'});
picturenames.push({name:'1 o\'clock'});

picturefiles.push({name:'numbers-zero.jpg'});
picturefiles.push({name:'numbers-one.jpg'});
picturefiles.push({name: 'time-1.jpg'});

var textToFindLower = "0";

var matches = picturenames.filter(function(windowValue, index){

if(windowValue) {
    windowValue.index = index;
    return windowValue.name.indexOf(textToFindLower) >= 0;
}
});

console.log(matches);
like image 38
I. Ahmed Avatar answered Sep 19 '22 08:09

I. Ahmed