I have an array of words lets say
string[] myWords = { "Arizona", "District", "Court", "is", "located", "at", ".", "District", "court", "closed" };
I need to find an index of phrase "Arizona District Court" so the result should be
result = [0,1,2]
It should ignore the words "District Court" at index [7,8] because its not a phrase it doesn't have Arizona word before District Court, so should be ignored.
What I have tried is this loop
foreach (var word in myWords)
{
if (myWords.Any(word.ToLowerInvariant().Contains))
{
var wordIndex = word;
}
}
but it return all matches for me
CodePudding user response:
You could use this LINQ query using SequenceEqual
:
string[] myWords = { "Arizona", "District", "Court", "is", "located", "at", ".", "District", "court", "closed" };
string phraseToFind = "Arizona District Court";
string[] phrases = phraseToFind.Split(new[] { " " }, StringSplitOptions.RemoveEmptyEntries);
int[] firstMatchingSequenceIndexes = Enumerable.Range(0, myWords.Length)
.Where(index => myWords.Skip(index).Take(phrases.Length).SequenceEqual(phrases))
.Select(index => Enumerable.Range(index, phrases.Length).ToArray())
.FirstOrDefault();
https://dotnetfiddle.net/wq7Bv0
Explanation:
- the query checks each index of the myWords-array
- it takes a sub-sequence of it with Skip(index) and Take(length)
- it compares this part with the phraseToFind-array
- if they are equal the matching indexes are returned as int[]
- change
First()
toToArray
if you want all matches orCount()
if you want the count
Since you have asked, this is how you would get the complete list:
int[][] allMatchingSequenceIndexes = Enumerable.Range(0, myWords.Length)
.Where(index => myWords.Skip(index).Take(phrases.Length).SequenceEqual(phrases))
.Select(index => Enumerable.Range(index, phrases.Length).ToArray())
.ToArray();
If you want to ignore the case, so it doesn't matter if it's "arizona" or "Arizona", use the right StringComparer
in SequenceEqual
. For example:
.Where(index => .... .SequenceEqual(phrases, StringComparer.OrdinalIgnoreCase))