0

Example: first sequence (A,B,C,D) second sequence (X,A,Z,A,B,C,D,E,A)

The first sequence is contained in the second sequence from position 4 because the letters A, B, C, D appear in exactly the same order as the first sequence

char[] firstSequence = new char[] { 'A', 'B', 'C', 'D'};
char[] secondSequence = new char[] {'X','A','Z','A','B','C','D','E','A'}
  • 1
    What have you tried? Please provide your attempt so we can push you in the right direction. – Xaphas Oct 07 '19 at 07:21
  • try joining both (each join it to become string) sequences then checking if the other contains the first – Mohammad Ali Oct 07 '19 at 07:21
  • 1
    1. Does (A, B, C, D) contain itself `(A, B, C, D)`? 2. Does `(A, X, B, C, D)` contain `(A, B, C, D)`? – Dmitry Bychenko Oct 07 '19 at 07:22
  • what do you mean by "all instances"? do you need to count how many are there? the way you have formulated your question, it seems that you need to extract several strings that are already the same. also- please show what you have tried already, so that we can see what the problem is – Stucky Oct 07 '19 at 07:22
  • elaborate more your question. so you need code to search a pattern on a string ? – Ajay Kumar Oad Oct 07 '19 at 07:22
  • you mean just a subset check or they have to be "ordered"? https://stackoverflow.com/questions/332973/check-whether-an-array-is-a-subset-of-another – xdtTransform Oct 07 '19 at 07:24

4 Answers4

4

Note; at the time this answer was written it wasn't clear that sequences under discussion were arrays of char. This answer gives a more general advice for collections of strings or complex types. For arrays of char a specific optimisation of not having a string.Join separator or using the string constructor that takes a char array, would be an option; other answers mention this so I won't repeat it here


Not really sure how you're storing your sequences but hopefully they're enumerable in which case:

string.Join(",", haystackCollection).Contains(string.Join(",", needleCollection));

I used comma as a separator but you should use a character that never occurs in the actual collections

More full example:

var haystackCollection = "XAZABCDEA".ToCharArray();
var needleCollection = "ABCD".ToCharArray();

bool result = string.Join(",", haystackCollection).Contains(string.Join(",", needleCollection));

This is only reliable if your collections are strings of identical length . It becomes unreliable if the haystack could contain strings of varying length because a haystack of {"AB","AC"} doesn't contain a needle of {"B","A"} but this method would report that it does.

You could fudge it to be better by putting separators at the start and end of each string join op:

string s = ",";
(s+string.Join(s, haystackCollection)+s).Contains(s+string.Join(",", needleCollection)+s);

But it might be better at this point to switch method entirely. Also if you want to know the index it occurs at it's a bit trickier using this string join method because you'd have to use IndexOf and then repeatedly subtract the lengths of each element plus the separator to get back to the index. You might be better off using loops instead:

int idx = 0;
while(idx < haystack.Length){
  if(haystack[idx] == needle[0]){
    int i = 1;
    while(haystack[idx+i] == needle[i] && i<needle.Length)
      i++;
    if(i == needle.Length)
      return idx; // you found the start of the needle
  }
  idx++;
}

In this latter method we start looking through the haystack trying to find the first element of the needle. If we find it, we start a loop that checks the rest of the needle. That loop only keeps gong while it finds needle entries in the haystack. If the loop stops early then the index variable i won't increment all the way up to the length of the needle array so we can conclude that if the variable i is indeed equal to the the Length of the needle, the needle was found at the position idx in the haystack

For this method to work out you really need your collections to be indexable by Integer rather than just enumerable, unless you want to get more convoluted. Remember that if you're using List instead of Array then it's Count rather than Length

Caius Jard
  • 72,509
  • 5
  • 49
  • 80
  • it will work even if the separator was contained in the actual collections – Mohammad Ali Oct 07 '19 at 07:23
  • Or string.Join("", haystackCollection).IndexOf(string.Join("", needleCollection)) – Tohm Oct 07 '19 at 07:26
  • @MohammadAli I was thinking not to use a char from the collections just in case things are more complex than presented here, for example a haystack of `AA,AA` and a needle of `A,A` - if you use A as a separator it will misreport that the haystack contains the needle – Caius Jard Oct 07 '19 at 07:39
  • @Tohm IndexOf would need some additional manipulation to remove the lengths of all the separators. If the haystack contains variable length strings that would cause further complications – Caius Jard Oct 07 '19 at 07:45
2

Convert your firstSequence and secondSequence into string and then use .Contains().

//Inputs
char[] firstSequence = new char[] { 'A', 'B', 'C', 'D'};
char[] secondSequence = new char[] {'X','A','Z','A','B','C','D','E','A'}

//Convert char array to string
string firstString = new string(firstSequence);
string secondString = new string(secondSequence);

//Use .Contains() to check string availability
bool isExist = secondString.Contains(firstString);

//Print message on console
Console.WriteLine(isExist ? "Sequence Exist" : "Sequence Not Exist");

//This will give you staring index of first string in second string i.e 3
//Next four will be your indexes that are 3, 4, 5, 6
if(isExist)
   {
       int startIndex = secondString.IndexOf(firstString);
       Console.WriteLine(string.Join(", ", Enumerable.Range(startIndex , firstString.Length)));
   }

Result:

Sequence Exist
3, 4, 5, 6

.NetFiddle

Prasad Telkikar
  • 15,207
  • 5
  • 21
  • 44
1

I'm not clear about your question , but if you mean that you want to find position of a string in another string you can use this :

  char[] firstSequence = new char[] { 'A', 'B', 'C', 'D'};
  char[] secondSequence = new char[] {'X','A','Z','A','B','C','D','E','A'}
  var firstString = new string(firstSequence);
  var secondString = new string(secondSequence);
  var positionIndex = secondString.IndexOf(fisrtString);
Prasad Telkikar
  • 15,207
  • 5
  • 21
  • 44
Ilia Afzali
  • 429
  • 2
  • 6
  • Yes I want. But I want to find the position of the vector.. In the example it would be 3,4,5,6 –  Oct 07 '19 at 07:47
  • hi Welcome to stackoverflow. I believe you are trying to find index of A,B,C,D in second string i.e. 'X','A','Z','A','B','C','D','E','A'. If this is the case then I updated your answer. If this is not the case then let me know I will revote it to previous state – Prasad Telkikar Oct 07 '19 at 08:56
0

If you want just to test that firstSequence items appear somewhere within secondSequence in the same order that in firstSequence, e.g.

 {A, X, A, B, P, Q, D, A, C, D}
        ^  ^              ^  ^  
        A  B              C  D      

You can try Linq Aggregate: having item a and index within firstSequence we want to match, we can compute index we want to match with next item in secondSequence

Code:

using System.Linq;

... 

bool contains = secondSequence.Aggregate(0, 
   (index, a) => (index >= firstSequence.Length) || (firstSequence[index] != a)
     ? index                               // match completed or nothing to macth 
     : index + 1) >= firstSequence.Length; // match next item

Same idea, but different Aggregate if all firstSequence must appear without interuptions:

 {A, X, A, B, C, D, P, Q}
        ^  ^  ^  ^  
        A  B  C  D  

Code:

using System.Linq;

... 

bool contains = secondSequence
  .Aggregate(0, (index, a) =>
       index >= firstSequence.Length ? index // match found, do nothing
     : firstSequence[index] == a ? index + 1 // can we match next item?
     : firstSequence[0] == a ? 1             // restart and match the 1st item
     : 0)                                    // restart
    >= firstSequence.Length;                 // Have we match all items?  
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • This post would hugely benefit from some surrounding explanation. As it stands it's effectively a code only answer because though it contains non code blocks it's effectively "here's a bunch of LINQ. It works" – Caius Jard Oct 07 '19 at 07:52