首页 > 解决方案 > 如何比较两个字符数组并查看位置?

问题描述

示例:第一个序列 (A,B,C,D) 第二个序列 (X,A,Z,A,B,C,D,E,A)

第一个序列包含在从位置 4 开始的第二个序列中,因为字母 A、B、C、D 出现的顺序与第一个序列完全相同

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

标签: c#arrayscharcomparison

解决方案


笔记; 在撰写此答案时,尚不清楚所讨论的序列是 char 数组。这个答案为字符串或复杂类型的集合提供了更一般的建议。对于 char 数组,可以选择不使用 string.Join 分隔符或使用带有 char 数组的字符串构造函数的特定优化;其他答案提到了这一点,所以我不会在这里重复


不太确定您如何存储序列,但希望在这种情况下它们是可枚举的:

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

我使用逗号作为分隔符,但您应该使用实际集合中从未出现过的字符

更完整的例子:

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

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

仅当您的集合是相同长度的字符串时,这才是可靠的。如果 haystack 可能包含不同长度的字符串,则变得不可靠,因为 haystack of{"AB","AC"}不包含 needle of{"B","A"}但此方法会报告它包含。

您可以通过在每个字符串连接操作的开头和结尾放置分隔符来使其更好:

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

但此时完全切换方法可能会更好。此外,如果您想知道它出现的索引,使用此字符串连接方法会有点棘手,因为您必须使用 IndexOf 然后反复减去每个元素的长度加上分隔符才能返回索引。您最好使用循环代替:

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++;
}

在后一种方法中,我们开始在大海捞针中寻找针的第一个元素。如果我们找到它,我们将启动一个循环来检查针的其余部分。只有当它在大海捞针中找到针头时,该循环才会保持锣声。如果循环提前停止,则索引变量i不会一直增加到针数组的长度,因此我们可以得出结论,如果变量i确实等于针的长度,则在该位置找到针idx大海捞针

要使这种方法可行,您确实需要您的集合可以被 Integer 索引,而不仅仅是可枚举的,除非您想变得更加复杂。请记住,如果您使用 List 而不是 Array 那么它是 Count 而不是 Length


推荐阅读