【问题标题】:How to compare two arrays of chars and see location?如何比较两个字符数组并查看位置?
【发布时间】:2019-10-07 07:15:18
【问题描述】:

示例:第一个序列 (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'}

【问题讨论】:

  • 你试过什么?请提供您的尝试,以便我们将您推向正确的方向。
  • 尝试加入两个(每个加入成为字符串)序列,然后检查另一个是否包含第一个
  • 1. (A, B, C, D) 是否包含自身(A, B, C, D)? 2.(A, X, B, C, D)是否包含(A, B, C, D)
  • “所有实例”是什么意思?你需要数一下有多少吗?按照您提出问题的方式,您似乎需要提取几个已经相同的字符串。另外-请展示您已经尝试过的内容,以便我们了解问题所在
  • 详细阐述您的问题。所以你需要代码来搜索字符串上的模式?

标签: c# arrays char comparison


【解决方案1】:

注意;在撰写此答案时,尚不清楚所讨论的序列是 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));

只有当您的集合是相同长度的字符串时,这才是可靠的。如果干草堆可能包含不同长度的字符串,则变得不可靠,因为{"AB","AC"} 的干草堆不包含{"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位置找到了针

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

【讨论】:

  • 即使分隔符包含在实际集合中,它也会起作用
  • 或 string.Join("", haystackCollection).IndexOf(string.Join("", needleCollection))
  • @MohammadAli 我在考虑不要使用集合中的字符,以防万一事情比这里介绍的更复杂,例如AA,AA 的干草堆和A,A 的针 - 如果你使用 A 作为分隔符,它会误报大海捞针包含针
  • @Tohm IndexOf 需要一些额外的操作来删除所有分隔符的长度。如果 haystack 包含会导致进一步复杂化的可变长度字符串
【解决方案2】:

将您的 firstSequence 和 secondSequence 转换为字符串,然后使用.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)));
   }

结果:

Sequence Exist
3, 4, 5, 6

.NetFiddle

【讨论】:

  • 如果你能输入答案。我没有偏好,可以循环也可以不循环。
  • @Hora,我用小提琴更新了我的答案,请检查
【解决方案3】:

我不清楚你的问题,但如果你的意思是你想在另一个字符串中找到一个字符串的位置,你可以使用这个:

  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);

【讨论】:

  • 是的,我想要。但我想找到向量的位置。在示例中它将是 3,4,5,6
  • 嗨,欢迎来到 stackoverflow。我相信您正在尝试在第二个字符串中查找 A、B、C、D 的索引,即 'X'、'A'、'Z'、'A'、'B'、'C'、'D'、'E ','一种'。如果是这种情况,那么我更新了您的答案。如果不是这种情况,请告诉我,我会将其恢复为以前的状态
【解决方案4】:

如果您只想测试firstSequence 项目是否以与firstSequence 中相同的顺序出现在secondSequence 中的某处,例如

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

你可以试试 Linq Aggregate: 有 aindex 在我们想要匹配的 firstSequence 中,我们可以计算 index 我们想要匹配的下一个项目secondSequence

代码:

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

相同的想法,但如果所有firstSequence 必须在没有中断的情况下出现,则Aggregate 不同:

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

代码:

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?  

【讨论】:

  • 这篇文章将从周围的一些解释中受益匪浅。就目前而言,它实际上是一个仅代码的答案,因为尽管它包含非代码块,但它实际上是“这是一堆 LINQ。它有效”
猜你喜欢
  • 1970-01-01
  • 2017-05-18
  • 1970-01-01
  • 1970-01-01
  • 2018-08-13
  • 2011-07-24
  • 2018-04-07
  • 2021-12-12
  • 2012-11-07
相关资源
最近更新 更多