0

I'm filtering the array of strings with a matching character. The task is to get the strings with the character "o" from first part of the word.

const fruits =["apple orange", "Orange", "banana", "banana", "apple"]

const character = "o"

const filterdFruits = fruits.filter((item) => item.charAt(0).toLowerCase() === character.toLowerCase())

console.log(filterdFruits)

The above logic will return the character matching with first letter of the string, which is Orange. But what I'm expecting here is to include Orange, apple orange as part my answer. There is reason why I want Orange to be in first place as it is an exact match and, while, apple orange is also a match but not an exact match. I'm reluctant to use regex here as I have the tendency to go wrong. Happy to get some directions :)

user2824374
  • 168
  • 3
  • 14
  • 2
    split by space and do the same in a loop – Walter Tross Jun 30 '22 at 10:53
  • `fruits.filter(item => item.toLowerCase().includes(character)).sort((a,b) => a.toLowerCase().indexOf(character) - b.toLowerCase().indexOf(character)) ` ? – cmgchess Jun 30 '22 at 10:58
  • @cmgchess "appric**o**t" does not start with "o". Neither does "carr**o**t". And many others. – VLAZ Jun 30 '22 at 11:01
  • @VLAZ now only i understood the question – cmgchess Jun 30 '22 at 11:02
  • @ cmgchess I attempted this way before, but order will go wrong if I have const fruits =["apple orange", "The Orange", "banana", "banana", "apple"]. In this case, I'd expect ["apple orange", "The Orange"] as the order because they fall in same position. – user2824374 Jun 30 '22 at 11:04
  • @user2824374 I added an answer, did you get a chance to look into that ? Hope that will work as per your expectation. – Debug Diva Jul 01 '22 at 12:51
  • @Rohit - It works for a single character, but not for more than 1. For instance character="or" is returning null array. I somehow managed to get this issue resolved using RegEx, but I couldn't get this done without using RegEx. – user2824374 Jul 04 '22 at 06:57
  • @user2824374 As we are doing comparision by using `charAt(0)` that's the reason it was not working for more than 1 character. I updated my answer. Now it will work as per your expectation. – Debug Diva Jul 04 '22 at 07:08
  • @RohìtJíndal - Thanks man. Substring helped. – user2824374 Jul 05 '22 at 00:48

4 Answers4

1

A small change to split each input on space(s) and to check each resulting word for a first letter of 'o' should work:

const fruits = ["apple orange", "Orange", "banana", "banana", "apple", 'plum kiwi Orange']

const character = "o"

const filterdFruits = fruits.filter((item) => { 
    return item.split(/\s+/).some(word => { 
        return word.charAt(0).toLowerCase() === character.toLowerCase()
    })
});

console.log(filterdFruits)
.as-console-wrapper { max-height: 100% !important; }
Terry Lennox
  • 29,471
  • 5
  • 28
  • 40
1

You can use this Regexp /\b[o]/gi to identify words starting with o

Important: this will match " Orange"

const fruits =["apple orange", "Orange", "banana", "banana", "apple"]
const filterdFruits = fruits.filter((item) => /\b[o]/i.test(item))

console.log(filterdFruits)
Ele
  • 33,468
  • 7
  • 37
  • 75
1

Depending on your strings in your array, using a regular expression (I know you said you were reluctant to use them as you feel you may go wrong, but I thought I'd show some examples) may be enough. Here we match on a word boundary \b, followed by an o:

const fruits =["apple orange", "Orange", "banana", "banana", "apple"]
const filterdFruits = fruits.filter(item => /\bo/i.test(item))
console.log(filterdFruits)

The word boundary is zero-length, and matches the following:

  • Before the first character in the string, if the first character is a word character.
  • After the last character in the string, if the last character is a word character.
  • Between two characters in the string, where one is a word character and the other is not a word character.

The first and last options allow us to match both "Orange" and "apple orange". Note that the word boundary matches between non-word characters, so apple $orange would also be a valid match. We can change the regex a little to fix this case, where we only match words that start with o (^o) or (|) have an o following a whitespace character \so that is not preceded by ((?<!)) the beginning of the string ^:

const fruits =["apple orange", "Orange", "banana", "banana", "apple"]
const filterdFruits = fruits.filter(item => /^o|(?<!^)\so/i.test(item))
console.log(filterdFruits)

In both expressions above, the /i means do a case-insensitive match. To make the above expressions dynamic so that they use the character, with can use the RegExp constructor, eg:

const fruits = ["apple orange", "Orange", "banana", "banana", "apple"];
const character = "o";
const filterdFruits = fruits.filter(item => new RegExp(String.raw`\b${character}`, 'i').test(item))
console.log(filterdFruits)

If character is user-supplied, you need to start worrying about escaping your character string so that regex can't be inserted as a value. There aren't any native ways to escape a string so that it can be used in a regular expression, so at that point, you might consider using a different approach such as Terry's

Nick Parsons
  • 45,728
  • 6
  • 46
  • 64
  • 1
    Thanks Nick. I like this approach `fruits.filter(item => new RegExp(String.raw`\b${character}`, 'i').test(item)).sort((a,b) => a.toLowerCase().indexOf(character) - b.toLowerCase().indexOf(character))` – user2824374 Jul 04 '22 at 06:59
1

Try this simple approach by just using Array.filter() along with Array.some() method.

Live Demo :

const fruits =["apple orange", "Orange", "banana", "banana", "apple"];

const character = "or";

const filterdFruits = fruits.filter((item) => {
  const subStrLength = character.length;
  return item.split(' ').some(el => el.substring(0, subStrLength).toLowerCase() === character.toLowerCase())
});

console.log(filterdFruits);
Debug Diva
  • 26,058
  • 13
  • 70
  • 123