比较两个字符串中的字符

发布于 2024-12-11 19:05:10 字数 417 浏览 0 评论 0原文

在C#中,如何比较两个字符串中的字符。
例如,假设我有这两个字符串
“bc3231dsc”和“bc3462dsc”

如何以编程方式找出字符串
都以“bc3”开头并以“dsc”结尾?

因此,给定的将是两个变量:

var1 = "bc3231dsc";  
var2 = "bc3462dsc";  

比较 var1 到 var2 中的每个字符后,我希望输出为:

leftMatch = "bc3";  
center1 = "231";  
center2 = "462";  
rightMatch = "dsc";  

条件:
1. 字符串的长度始终为 9 个字符。
2. 字符串不区分大小写。

In C#, how do I compare the characters in two strings.
For example, let's say I have these two strings
"bc3231dsc" and "bc3462dsc"

How do I programically figure out the the strings
both start with "bc3" and end with "dsc"?

So the given would be two variables:

var1 = "bc3231dsc";  
var2 = "bc3462dsc";  

After comparing each characters from var1 to var2, I would want the output to be:

leftMatch = "bc3";  
center1 = "231";  
center2 = "462";  
rightMatch = "dsc";  

Conditions:
1. The strings will always be a length of 9 character.
2. The strings are not case sensitive.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

若言繁花未落 2024-12-18 19:05:10

string 类有 2 个可以使用的方法(StartsWith 和 Endwith)。

The string class has 2 methods (StartsWith and Endwith) that you can use.

挽容 2024-12-18 19:05:10

在阅读了您的问题和已经给出的答案后,我认为缺少一些限制,这对您来说可能是显而易见的,但对社区而言却并非如此。但也许我们可以做一些猜测:

  1. 您将有一堆应该进行比较的字符串对。
  2. 每对中的两个字符串具有相同的长度,或者您只对比较从左到右同时读取的字符感兴趣。
  3. 获取某种枚举来告诉我每个块从哪里开始以及它有多长。

事实上,字符串只是字符的枚举,您可以在此处使用 LINQ 来了解匹配的字符,如下所示:

private IEnumerable<bool> CommonChars(string first, string second)
{
    if (first == null)
        throw new ArgumentNullException("first");

    if (second == null)
        throw new ArgumentNullException("second");

    var charsToCompare = first.Zip(second, (LeftChar, RightChar) => new { LeftChar, RightChar });
    var matchingChars = charsToCompare.Select(pair => pair.LeftChar == pair.RightChar);

    return matchingChars;
}

这样我们就可以继续,现在找出每个连续 true 和 false 标志块的长度使用此方法:

private IEnumerable<Tuple<int, int>> Pack(IEnumerable<bool> source)
{
    if (source == null)
        throw new ArgumentNullException("source");

    using (var iterator = source.GetEnumerator())
    {
        if (!iterator.MoveNext())
        {
            yield break;
        }

        bool current = iterator.Current;
        int index = 0;
        int length = 1;

        while (iterator.MoveNext())
        {
            if(current != iterator.Current)
            {
                yield return Tuple.Create(index, length);
                index += length;
                length = 0;
            }

            current = iterator.Current;
            length++;
        }

        yield return Tuple.Create(index, length);
    }
}

目前我不知道是否已有 LINQ 函数提供相同的功能。据我已经读过,它应该可以使用 SelectMany() (因为理论上你可以使用此方法完成任何 LINQ 任务),但作为临时实现,上面的方法更容易(对我来说) 。

然后可以以如下方式使用这些函数:

var firstString = "bc3231dsc";
var secondString = "bc3462dsc";

var commonChars = CommonChars(firstString, secondString);
var packs = Pack(commonChars);

foreach (var item in packs)
{
    Console.WriteLine("Left side:  " + firstString.Substring(item.Item1, item.Item2));
    Console.WriteLine("Right side: " + secondString.Substring(item.Item1, item.Item2));
    Console.WriteLine();
}

然后您会给出以下输出:

左侧: bc3
右侧:bc3

左侧:231
右侧:462

左侧:dsc
右侧:dsc

最大的缺点是在某种程度上使用 Tuple 导致它导致丑陋的属性名称 Item1Item2 相距甚远立即可读。但如果确实需要,您可以引入自己的简单类,其中包含两个整数并具有一些坚如磐石的属性名称。目前,关于每个块是否由两个字符串共享或者它们是否不同的信息也丢失了。但同样,将这些信息也放入元组或您自己的类中应该相当简单。

After reading your question and the already given answers i think there are some constraints are missing, which are maybe obvious to you, but not to the community. But maybe we can do a little guess work:

  1. You'll have a bunch of string pairs that should be compared.
  2. The two strings in each pair are of the same length or you are only interested by comparing the characters read simultaneously from left to right.
  3. Get some kind of enumeration that tells me where each block starts and how long it is.

Due to the fact, that a string is only a enumeration of chars you could use LINQ here to get an idea of the matching characters like this:

private IEnumerable<bool> CommonChars(string first, string second)
{
    if (first == null)
        throw new ArgumentNullException("first");

    if (second == null)
        throw new ArgumentNullException("second");

    var charsToCompare = first.Zip(second, (LeftChar, RightChar) => new { LeftChar, RightChar });
    var matchingChars = charsToCompare.Select(pair => pair.LeftChar == pair.RightChar);

    return matchingChars;
}

With this we can proceed and now find out how long each block of consecutive true and false flags are with this method:

private IEnumerable<Tuple<int, int>> Pack(IEnumerable<bool> source)
{
    if (source == null)
        throw new ArgumentNullException("source");

    using (var iterator = source.GetEnumerator())
    {
        if (!iterator.MoveNext())
        {
            yield break;
        }

        bool current = iterator.Current;
        int index = 0;
        int length = 1;

        while (iterator.MoveNext())
        {
            if(current != iterator.Current)
            {
                yield return Tuple.Create(index, length);
                index += length;
                length = 0;
            }

            current = iterator.Current;
            length++;
        }

        yield return Tuple.Create(index, length);
    }
}

Currently i don't know if there is an already existing LINQ function that provides the same functionality. As far as i have already read it should be possible with SelectMany() (cause in theory you can accomplish any LINQ task with this method), but as an adhoc implementation the above was easier (for me).

These functions could then be used in a way something like this:

var firstString = "bc3231dsc";
var secondString = "bc3462dsc";

var commonChars = CommonChars(firstString, secondString);
var packs = Pack(commonChars);

foreach (var item in packs)
{
    Console.WriteLine("Left side:  " + firstString.Substring(item.Item1, item.Item2));
    Console.WriteLine("Right side: " + secondString.Substring(item.Item1, item.Item2));
    Console.WriteLine();
}

Which would you then give this output:

Left side: bc3
Right side: bc3

Left side: 231
Right side: 462

Left side: dsc
Right side: dsc

The biggest drawback is in someway the usage of Tuple cause it leads to the ugly property names Item1 and Item2 which are far away from being instantly readable. But if it is really wanted you could introduce your own simple class holding two integers and has some rock-solid property names. Also currently the information is lost about if each block is shared by both strings or if they are different. But once again it should be fairly simply to get this information also into the tuple or your own class.

来日方长 2024-12-18 19:05:10
    static void Main(string[] args)
    {
        string test1 = "bc3231dsc";
        string tes2 = "bc3462dsc";
        string firstmatch = GetMatch(test1, tes2, false);
        string lasttmatch = GetMatch(test1, tes2, true);
        string center1 = test1.Substring(firstmatch.Length, test1.Length -(firstmatch.Length + lasttmatch.Length)) ;
        string center2 = test2.Substring(firstmatch.Length, test1.Length -(firstmatch.Length + lasttmatch.Length)) ;

    }

    public static string GetMatch(string fist, string second, bool isReverse)
    {
        if (isReverse)
        {
            fist = ReverseString(fist);
            second = ReverseString(second);
        }
        StringBuilder builder = new StringBuilder();
        char[] ar1 = fist.ToArray();
        for (int i = 0; i < ar1.Length; i++)
        {
            if (fist.Length > i + 1 && ar1[i].Equals(second[i]))
            {
                builder.Append(ar1[i]);
            }
            else
            {
                break;
            }
        }
        if (isReverse)
        {
            return ReverseString(builder.ToString());
        }
        return builder.ToString();
    }

    public static string ReverseString(string s)
    {
        char[] arr = s.ToCharArray();
        Array.Reverse(arr);
        return new string(arr);
    }
    static void Main(string[] args)
    {
        string test1 = "bc3231dsc";
        string tes2 = "bc3462dsc";
        string firstmatch = GetMatch(test1, tes2, false);
        string lasttmatch = GetMatch(test1, tes2, true);
        string center1 = test1.Substring(firstmatch.Length, test1.Length -(firstmatch.Length + lasttmatch.Length)) ;
        string center2 = test2.Substring(firstmatch.Length, test1.Length -(firstmatch.Length + lasttmatch.Length)) ;

    }

    public static string GetMatch(string fist, string second, bool isReverse)
    {
        if (isReverse)
        {
            fist = ReverseString(fist);
            second = ReverseString(second);
        }
        StringBuilder builder = new StringBuilder();
        char[] ar1 = fist.ToArray();
        for (int i = 0; i < ar1.Length; i++)
        {
            if (fist.Length > i + 1 && ar1[i].Equals(second[i]))
            {
                builder.Append(ar1[i]);
            }
            else
            {
                break;
            }
        }
        if (isReverse)
        {
            return ReverseString(builder.ToString());
        }
        return builder.ToString();
    }

    public static string ReverseString(string s)
    {
        char[] arr = s.ToCharArray();
        Array.Reverse(arr);
        return new string(arr);
    }
-小熊_ 2024-12-18 19:05:10

你需要的伪代码..

int stringpos = 0
string resultstart = ""
while not end of string (either of the two)
{
if string1.substr(stringpos) == string1.substr(stringpos) 
resultstart =resultstart + string1.substr(stringpos)
else
exit while
}

resultstart 让你开始字符串.. 你可以向后做同样的事情...

Pseudo code of what you need..

int stringpos = 0
string resultstart = ""
while not end of string (either of the two)
{
if string1.substr(stringpos) == string1.substr(stringpos) 
resultstart =resultstart + string1.substr(stringpos)
else
exit while
}

resultstart has you start string.. you can do the same going backwards...

一绘本一梦想 2024-12-18 19:05:10

您可以使用的另一个解决方案是正则表达式。

Regex re = new Regex("^bc3.*?dsc$");
String first = "bc3231dsc";
if(re.IsMatch(first)) {
    //Act accordingly...
}

这让您在匹配时更加灵活。上面的模式匹配以 bc3 开头并以 dsc 结尾的任何字符串,中间包含除换行符之外的任何内容。通过改变.*?对于 \d,您可以指定只需要两个字段之间的数字。从那里开始,可能性是无限的。

Another solution you can use is Regular Expressions.

Regex re = new Regex("^bc3.*?dsc$");
String first = "bc3231dsc";
if(re.IsMatch(first)) {
    //Act accordingly...
}

This gives you more flexibility when matching. The pattern above matches any string that starts in bc3 and ends in dsc with anything between except a linefeed. By changing .*? to \d, you could specify that you only want digits between the two fields. From there, the possibilities are endless.

寂寞陪衬 2024-12-18 19:05:10
using System;
using System.Text.RegularExpressions;
using System.Collections.Generic;

class Sample {
    static public void Main(){
        string s1 = "bc3231dsc";
        string s2 = "bc3462dsc";
        List<string> common_str = commonStrings(s1,s2);
        foreach ( var s in common_str)
            Console.WriteLine(s);
    }
    static public List<string> commonStrings(string s1, string s2){
        int len = s1.Length;
        char [] match_chars = new char[len];
        for(var i = 0; i < len ; ++i)
            match_chars[i] = (Char.ToLower(s1[i])==Char.ToLower(s2[i]))? '#' : '_';
        string pat = new String(match_chars);
        Regex regex = new Regex("(#+)", RegexOptions.Compiled);
        List<string> result = new List<string>();
        foreach (Match match in regex.Matches(pat))
            result.Add(s1.Substring(match.Index, match.Length));
        return result;
    }
}
using System;
using System.Text.RegularExpressions;
using System.Collections.Generic;

class Sample {
    static public void Main(){
        string s1 = "bc3231dsc";
        string s2 = "bc3462dsc";
        List<string> common_str = commonStrings(s1,s2);
        foreach ( var s in common_str)
            Console.WriteLine(s);
    }
    static public List<string> commonStrings(string s1, string s2){
        int len = s1.Length;
        char [] match_chars = new char[len];
        for(var i = 0; i < len ; ++i)
            match_chars[i] = (Char.ToLower(s1[i])==Char.ToLower(s2[i]))? '#' : '_';
        string pat = new String(match_chars);
        Regex regex = new Regex("(#+)", RegexOptions.Compiled);
        List<string> result = new List<string>();
        foreach (Match match in regex.Matches(pat))
            result.Add(s1.Substring(match.Index, match.Length));
        return result;
    }
}
第几種人 2024-12-18 19:05:10

对于更新条件

using System;

class Sample {
    static public void Main(){
        string s1 = "bc3231dsc";
        string s2 = "bc3462dsc";
        int len = 9;//s1.Length;//cond.1)
        int l_pos = 0;
        int r_pos = len;
        for(int i=0;i<len && Char.ToLower(s1[i])==Char.ToLower(s2[i]);++i){
            ++l_pos;
        }
        for(int i=len-1;i>0 && Char.ToLower(s1[i])==Char.ToLower(s2[i]);--i){
            --r_pos;
        }
        string leftMatch = s1.Substring(0,l_pos);
        string center1 = s1.Substring(l_pos, r_pos - l_pos);
        string center2 = s2.Substring(l_pos, r_pos - l_pos);
        string rightMatch = s1.Substring(r_pos);
        Console.Write(
        "leftMatch = \"{0}\"\n" +
        "center1 = \"{1}\"\n" +
        "center2 = \"{2}\"\n" +
        "rightMatch = \"{3}\"\n",leftMatch, center1, center2, rightMatch);
    }
}

for UPDATE CONDITION

using System;

class Sample {
    static public void Main(){
        string s1 = "bc3231dsc";
        string s2 = "bc3462dsc";
        int len = 9;//s1.Length;//cond.1)
        int l_pos = 0;
        int r_pos = len;
        for(int i=0;i<len && Char.ToLower(s1[i])==Char.ToLower(s2[i]);++i){
            ++l_pos;
        }
        for(int i=len-1;i>0 && Char.ToLower(s1[i])==Char.ToLower(s2[i]);--i){
            --r_pos;
        }
        string leftMatch = s1.Substring(0,l_pos);
        string center1 = s1.Substring(l_pos, r_pos - l_pos);
        string center2 = s2.Substring(l_pos, r_pos - l_pos);
        string rightMatch = s1.Substring(r_pos);
        Console.Write(
        "leftMatch = \"{0}\"\n" +
        "center1 = \"{1}\"\n" +
        "center2 = \"{2}\"\n" +
        "rightMatch = \"{3}\"\n",leftMatch, center1, center2, rightMatch);
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文