0

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.

ExtraSun
  • 528
  • 2
  • 11
  • 31
  • What is the actual problem? Removing the spaces and such? Since the string 'Oasis - Don't Look Back In Anger' without spaces and in lowercase is 'oasisdontlookbackinanger', so your .includes() check should find it. – Shilly Nov 30 '18 at 11:30
  • @Shilly I need it to find only the word which start twith the letter I pressed, than the second (the third and so on). As for now it don't ignore the chars and spaces. – ExtraSun Nov 30 '18 at 11:34

3 Answers3

1
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);
Sagar Jajoriya
  • 2,377
  • 1
  • 9
  • 17
1

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.

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
0

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

Walidovic
  • 21
  • 1
  • 7