-2

I have word(s) with one or more prefixes (starting letters) and a list of predefined prefixes. I want to count the number of prefixes attached to the given word. My Code:

public static void main(string[] args)
{
    List<string> prefixes=new List<string>();
    prefixes.Add("im");
    prefixes.Add("anti");
    prefixes.Add("auto");
    prefixes.Add("dis");
    Console.Write(PrefixesCount("autoDiscount",prefixes));
}

public static int PrefixesCount(string word,List<string> prefixes)
{
    return (from t in prefixes where word.StartWith(t) select t).ToList<string>().Count;
}

output: 1

It should return "2" as "auto" and "dis" are prefixes.

thehennyy
  • 4,020
  • 1
  • 22
  • 31
rtraees
  • 312
  • 2
  • 15
  • Firstly "autoDiscount" doesn't start with "dis" it contains "dis", Secondly, You need to deal with the Upper and lower cases characters. – Ayoub_B Oct 18 '17 at 06:36
  • yes Auto discount doesn't start with "dis" but it start with "auto" if i remove "auto" then again it start with a prefix word "dis", case sensitivity is not a big issue, I can use ToUpper() function on both to make it case in-insensitive @Ayoub_B – rtraees Oct 18 '17 at 06:41
  • Do you must use LINQ? – Ofir Winegarten Oct 18 '17 at 06:42
  • What count should be returned in case when word is `antiPattern` and prefixes are `[ "anti", "an" ]`? – Fabio Oct 18 '17 at 06:58
  • 1
    @EdwardIslam can you explain the logic for counting in "sco" as well? i don't see why – Ofir Winegarten Oct 18 '17 at 06:59
  • @EdwardIslam, another case - what result you expect for word `"antiPattern"` and prefixes `[ "anti", "an", "at" ]` – Fabio Oct 18 '17 at 08:00

4 Answers4

3

You should use IndexOf instead of starts with as there are 2 words you are trying to find inside the string, and your string can only start with one word.

Also, use ignoreCase while doing a comparison to discard issues related to Lowercase and Uppercase comparisons.

public static int PrefixesCount(string word, List<string> prefixes)
{
    return (from t in prefixes where word.IndexOf(t, 
   StringComparison.CurrentCultureIgnoreCase) >-1 select t).Count();
}
Amit Kumar Singh
  • 4,393
  • 2
  • 9
  • 22
  • 2
    `.ToList()` is redundant here. You can drop it and use `Count()` instead. – Tsahi Asher Oct 18 '17 at 06:41
  • 1
    This will not work for OP's requirements, because he need prefixes, this approach will count all occurrences of "prefixes" even it in the end of the word – Fabio Oct 18 '17 at 06:44
  • @Fabio as mentioned in his comments, he wants to count sco also, which is in middle of the word somewhere. – Amit Kumar Singh Oct 18 '17 at 07:49
  • @TsahiAsher I used his query from the question used `IndexOf` instead of `StartsWith`, Now have removed `.ToList() `since you are correct, it is not required to get the count only. – Amit Kumar Singh Oct 18 '17 at 07:51
  • 1
    Then it definitely cannot be names as `PrefixesCount` - it become simply string contains method - which have tons of answers on SO – Fabio Oct 18 '17 at 07:58
1

I would go for a simple while loop instead as it's more intuitive, reads and explains itself better.

The loop will continue as long as it finds a prefix and if it does, it removes it from the word.

public static int PrefixesCount(string word, List<string> prefixes)
{
    string prefix;
    int count = 0;
    while ((prefix = prefixes.FirstOrDefault(p => word.StartsWith(p,StringComparison.InvariantCultureIgnoreCase))) != null)
    {
        word = word.Substring(prefix.Length);
        count++;
    }

    return count;
}
Ofir Winegarten
  • 9,215
  • 2
  • 21
  • 27
  • OP wasn't specific in requirements, for example this will not work in case when prefixes contains other prefixes, but still need to be count. For example prefixes are [ "anti", "an" ], after "anti" prefix found it will remove it by substring and "an" will not be count – Fabio Oct 18 '17 at 06:50
  • @fabio, is that *really* the requirement? doesn't make sense to me. but we can find many edge cases. for example the prefixes could be ["anti", "an", "ti"] - then what? who knows... My answers and the others as well follows the logic that the OP introduced in his first comment – Ofir Winegarten Oct 18 '17 at 06:54
0

For that you have to go recursive. For example:

using System.Linq;
private int CntPref(List<string> prefs, string aword) {
    int cnt = 0;
    prefs.Select((s)=>{
        if(aword.StartsWith(s)) {
            cnt++;
            cnt+=CntPrefs(prefs, aword.Substring(s.Length));
        }
    });
    return cnt,
}
casiosmu
  • 797
  • 1
  • 8
  • 22
  • OP wasn't specific in requirements, for example this will not work in case when prefixes contains other prefixes, but still need to be count. For example prefixes are [ "anti", "an" ], after "anti" prefix found it will remove it by `substring` and "an" will not be count. – Fabio Oct 18 '17 at 06:49
0

You can use this, I solved Lambda and Linq without using StringComparison. You could write an extension method for containing control in the extension method, then you obtain ignore case sensitivity with StringComparison. Like Case insensitive 'Contains(string)' check the @JaredPar's answer.

 public static int PrefixesCount(string word, List<string> prefixes)
 {        
     var prefixCountWithLinq = from p in prefixes
                              where word.ToLower().Contains(p)
                              select(p).ToList();

     var prefixCountWithlamda = prefixes.Count(x => word.ToLower().Contains(x));

     return prefixCountWithLinq.Count();
  }

Return: 2

Hope it helps to you.

arslanaybars
  • 1,813
  • 2
  • 24
  • 29