0

I have a list of strings with the below format :

  • full1
  • full1inc1
  • full1inc2
  • full1inc3
  • full2
  • full2inc1
  • full2inc2
  • full3
  • ...
  • ....
  • full100inc100

Basically, the integer value after the "full" can be any number and the "inc" may or may not be there.

I have to pick an arbitrary string from this list , let's say the "full32" or the "full32inc1" and isolate the substring "full" along with the number that follows and put it in another string.

How could I do this? Should I use Regex or String Matching ?

Community
  • 1
  • 1
Aman Mehrotra
  • 373
  • 4
  • 7
  • 15

4 Answers4

1

In one line:

var matches = yourString.Split("\r\n".ToCharArray()).Where(s => s.StartsWith("full32"));

Requires LINQ, and is the conceptual equivalent of:

string[] lines = yourString.Split("\r\n".ToCharArray());
List<string> matches = new List<string>();
foreach(string s in lines)
  if(s.StartsWith("full32"))
    matches.Add(s);

Which may be more readable to you.

If you wanted to use Regex, something like this would capture them:

Regex r = new Regex("(?<f>full32(inc\d+)?)");
foreach(Match m in r.Matches(yourString))
  MessageBox.Show(m.Groups["f"].Value);

In all these examples, where you see "full32" in a string, that is where you should parameterize with a variable if you want to search for strings other than full32

Caius Jard
  • 72,509
  • 5
  • 49
  • 80
  • Hi, full'32' i've provided only as an example. The real problem is that i do not know what integer value will be after full. I obtain this string/name from folder names based on the date the user puts in. – Aman Mehrotra Jun 05 '13 at 11:02
1

Update according to this comment on my question "what's the desired result for full100inc100?"

The desired result would be full100

Then it's as easy as:

var isolatedList = listOfString
.Select(str => "full" + new string(
    str.Reverse()               // this is a backwards loop in Linq
       .TakeWhile(Char.IsDigit) // this takes chars until there is a non-digit char
       .Reverse()               // backwards loop to pick the digit-chars in the correct order
       .ToArray()               // needed for the string constructor
));

And if you want only the first number after "full":

var isolatedList = listOfString
    .Where(str => str.StartsWith("full"))
    .Select(str => "full" + new string(str.Substring("full".Length)
                                          .TakeWhile(Char.IsDigit)
                                          .ToArray()));

Demo

full1
full1
full2
full3
full2
full1
full2
full3
full100

Perhaps this:

var isolatedList = listOfString
    .Where(str => str.StartsWith("full"))
    .Select(str => "full" + string.Join("_", str.Substring("full".Length).Split(new[]{"inc"}, StringSplitOptions.None)))
    .ToList();

Change the separator in String.Join accordingly or just use the logic without linq:

"full" + 
string.Join("_", 
    str.Substring("full".Length).Split(new[]{"inc"}, StringSplitOptions.None))

Demo

full1
full1_1
full1_2
full1_3
full2
full2_1
full2_2
full3
full100_100
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
  • I'm suppose to get the number that follows full, not the number at the end. inc and the number that follows inc may or may not be there in the string. So, i can't isolate it based on the data before string. – Aman Mehrotra Jun 05 '13 at 11:09
  • @AmanMehrotra: Edited again to provide a way to get the first number after "full". – Tim Schmelter Jun 05 '13 at 11:16
  • 1
    @TimSchmelter, would it not be easier to use RegEx to retrieve it instead of string/LINQ manipulation if he only wants the number after `full`? – Bob. Jun 05 '13 at 12:19
  • @Bob.: Since my regex skills are still weak and because string methods are more efficient and Linq is often more readable i prefer this way. However, if you have a simple regex it might be the better approach. – Tim Schmelter Jun 05 '13 at 12:31
  • @TimSchmelter, I've posted my answer [here](http://stackoverflow.com/a/16940638/1466627), it looks simplier and I think easier to manipulate without too much knowledge. – Bob. Jun 05 '13 at 12:59
1

Based on your description, it seems like it might be possible that the strings are not guaranteed to be consistent. The following code will construct a List<String> of delimited (parsed) lines based on an incoming list of unknown content. It's a bit of a "brute force" method, but should allow for flexibility in the incoming list. Here is the code:

List<String> list = new List<String>();
list.Add("full1");
list.Add("full1inc1");
list.Add("full1inc2");
list.Add("full1inc3");
list.Add("full2");
list.Add("full2inc1");
list.Add("full2inc2");
list.Add("full3");
List<String> lines = new List<String>();
foreach (String str in list)
{
    String tmp = String.Empty;
    StringBuilder sb1 = new StringBuilder();
    StringBuilder sb2 = new StringBuilder();
    foreach (Char ch in str.ToCharArray())
    {
        if (Char.IsLetter(ch))
        {
            if (!String.IsNullOrEmpty(sb2.ToString()))
            {
              tmp += sb2.ToString() + ",";
                sb2 = new StringBuilder();
            }
            sb1.Append(ch);
        }
        else
        {
            if (!String.IsNullOrEmpty(sb1.ToString()))
            {
                tmp += sb1.ToString() + ",";
                sb1 = new StringBuilder();
            }
            sb2.Append(ch);
        }
    }
    if (!String.IsNullOrEmpty(sb1.ToString()))
        tmp += sb1.ToString() + ",";
    if (!String.IsNullOrEmpty(sb2.ToString()))
        tmp += sb2.ToString() + ",";
    lines.Add(tmp);
    for (Int32 i = 0; i < lines.Count; i++)
        lines[i] = lines[i].TrimEnd(',');
}

So, based on your example list, here's what you will get:

full1  -->  "full,1"

full1inc1  -->  "full,1,inc,1"

full1inc2  -->  "full,1,inc,2"

full1inc3  -->  "full,1,inc,3"

full2  -->  "full,2"

full2inc1  -->  "full,2,inc,1"

full2inc2  -->  "full,2,inc,2"

full3  -->  "full,3"

full100inc100  -->  "full,100,inc,100"

With this method, you will not need to presume that "full" is the leading string, or that it is followed by "inc" (or really anything at all).

Once you have the resulting delimited list, and because you know that the pattern is StringNumberStringNumber, you can then use whatever means you like to split those delimited lines into pieces and use them as you like.

DonBoitnott
  • 10,787
  • 6
  • 49
  • 68
1

The quickest way would be to brute force, but personally, the simpliest way I find would be to match a specific pattern, in this case full followed by a number.

string myString = "full1\nfull2s"; // Strings
List<string> listOfStrings = new List<string>(); // List of strings
listOfStrings.Add(myString);
Regex regex = new Regex(@"full[0-9]+"); // Pattern to look for
StringBuilder sb = new StringBuilder();
foreach(string str in listOfStrings) {
    foreach(Match match in regex.Matches(str)) { // Match patterns
        sb.AppendLine(match.Value);
    }
}

MessageBox.Show(sb.ToString());
Bob.
  • 3,894
  • 4
  • 44
  • 76