ExtraSun
ExtraSun

Reputation: 548

Creating a search function for strings in Javascript - React Native

I'm trying to create a function which will search a specific words.

For example if I tap the letter "O" the first result will be the word "Oasis" (and not "U2 - Still Haven't Found What I'm..." and all the other songs that has "O" in their words), or any other middle word.
It need to ignore spaces - " ", the char "-" (" "-" ") and ' or other chars, so it will connect all thw words together.
For example when I tap "dontlookbackin" the search will find the word which is starting with the first letter I pressed, than the other letter in the word and so on.

So far I'm only able to make a simple search - to find every word that contains the first letter I pressed.

The specific part of the "search" function :

 SearchSong = () => {
    console.log("Pressed")
    var e = this.state.searchRes;
    if (e == "") {
      return;
    }
    var musicList = [];
    var songs = [];
    if (this.state.songs != null) {
      songs = this.state.songs;  
       musicList = songs.filter(song =>
        song.Song_Name.toLowerCase().includes(e.toLowerCase())
      );

Example of the current search - The corrent simple search

If more detials and fixes are needed please tell me.

Upvotes: 0

Views: 4183

Answers (3)

Sagar Jajoriya
Sagar Jajoriya

Reputation: 2375

let strKeyword = "string001";
    musicList = [];
    songsLength = songs.length;

for (i = 0; i < songsLength; i++) {
    if (songs[i].Song_Name.replace(/[^a-zA-Z0-9]/g, "").substr(0, strKeyword.length).toLowerCase() == strKeyword.toLowerCase()) {
        musicList.push(songs[i]);
    }
}

console.log(musicList);

Upvotes: 1

Walidovic
Walidovic

Reputation: 21

Try this: song.Song_Name.toLowerCase().startsWith(e.toLowerCase())

Upvotes: 0

T.J. Crowder
T.J. Crowder

Reputation: 1074276

Something along these lines should get you started (see comments):

function removeUnwantedChars(str) {
    return str.replace(/\W/g, "");
}

function search(str) {
    // Create regex like "abc" becomes "^a.*b.*c"
    str = removeUnwantedChars(str);
    if (!str) {
        return [];
    }
    const searchRex = new RegExp(
        "^" +
        RegExp.escape(str.charAt(0)) + [...str.substring(1)].map(ch =>
            ".*" + RegExp.escape(ch)
        ).join(""),
        "i"
    );
    // Search for matches
    return songs.filter(song => searchRex.test(song.Song_Name.replace(/\W/g, "")));
}

...using a regex escape function along the lines of the ones in this question's answers.

Live Example:

if (!RegExp.escape) {
    RegExp.escape = function(string) {
      return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
    };
}

const songs = [
    {Song_Name: "U2 - I Still Haven't Found What I'm Looking For"},
    {Song_Name: "Oasis - Champagne Supernova"},
    {Song_Name: "Oasis - Don't Look Back In Anger"},
    {Song_Name: "The Rolling Stones - Like A Rolling Stone"}
];

function removeUnwantedChars(str) {
    return str.replace(/\W/g, "");
}

function search(str) {
    // Create regex like "abc" becomes "^a.*b.*c"
    str = removeUnwantedChars(str);
    if (!str) {
        return [];
    }
    const searchRex = new RegExp(
        "^" +
        RegExp.escape(str.charAt(0)) + [...str.substring(1)].map(ch =>
            ".*" + RegExp.escape(ch)
        ).join(""),
        "i"
    );
    // Search for matches
    return songs.filter(song => searchRex.test(song.Song_Name.replace(/\W/g, "")));
}

const testStrings = [
  "oasisdontlookbackin",
  "oasisanger",
  "therollstone",
  "rolling" // no match
];
for (const str of testStrings) {
  console.log(str, "=>", search(str));
}
.as-console-wrapper {
  max-height: 100% !important;
}

The .* in the regex means "any number of any character here" which means that you don't have to type every significant character after the first one (which is why "oasisanger" works). But it does incorporate your requirement that the first character match the first character of the name.

Upvotes: 1

Related Questions