C N
C N

Reputation: 449

compare the characters in two strings

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.

Upvotes: 1

Views: 28754

Answers (7)

Damith
Damith

Reputation: 63065

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

Upvotes: 1

BLUEPIXY
BLUEPIXY

Reputation: 40145

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

Upvotes: 0

Oliver
Oliver

Reputation: 45071

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.

Upvotes: 2

BLUEPIXY
BLUEPIXY

Reputation: 40145

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

Upvotes: 0

Dirk Dastardly
Dirk Dastardly

Reputation: 1047

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.

Upvotes: 0

gbianchi
gbianchi

Reputation: 2138

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...

Upvotes: 0

Tundey
Tundey

Reputation: 2965

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

Upvotes: 5

Related Questions