0
Updated - When searched value is in middle

string text = "Trio charged over alleged $100m money laundering syndicate at Merrylands, Guildford West";
string searchtext= "charged over";
string[] fragments = text.Split(new string[] { searchtext }, StringSplitOptions.None);

    //Fragments
   //if [0] is blank searched text is in the beginning - searchedtext + [1]
  //if [1] is blank searched text is in the end - [0] + searched text
  // If searched text is in middle then both items has value - [0] + seachedtext + [1]

 //This loop will execute only two times because it can have maximum 2 values, issue will
 //come when searched value is in middle (loop should run 3 times) as for the searched value i have to apply differnt logic (like change background color of the text)
 // and dont change background color for head and tail
 //How do i insert searched value in middle of [0] and [1] ??

I am having a string without delimeter which i am trying to split based on searched string. My requirement is split the string into two , one part contains string without the searchtext and other contains searchtext like below-

 Original String - "Bitcoin ATMs Highlight Flaws in EU Money Laundering Rules"
    String 1 - Bitcoin ATMs Highlight Flaws in EU 
    String 2 - Money Laundering Rules

I have written below code it works for the above sample value, but it failed for 

Failed - Not returning String 1 and String 2, String is empty
string watch = " Money Laundering Rules Bitcoin ATMs Highlight Flaws in EU";
string serachetxt = "Money Laundering Rules";

This works -

List<string> matchedstr = new List<string>();
string watch = "Bitcoin ATMs Highlight Flaws in EU Money Laundering Rules";
string serachetxt = "Money Laundering Rules";

string compa = watch.Substring(0,watch.IndexOf(serachetxt)); //It returns "Bitcoin ATMs Highlight Flaws in EU"

matchedstr.Add(compa);
matchedstr.Add(serachetxt);

foreach(var itemco in matchedstr)
{

}

Bokambo
  • 4,204
  • 27
  • 79
  • 130
  • 5
    The question is not very clear; let's try to crisp it up a bit. Suppose the source string was "ABC" and the search string was "B". What would you expect the outputs to be? Suppose the search string was "D"; what would you expect the outputs to be? – Eric Lippert Apr 23 '20 at 18:11
  • @EricLippert : Good catch...For "ABC" I want three seperate strings "A","B","C" so basically there will head and tail of the searched in this case. And if searched string was "D" return the source string – Bokambo Apr 23 '20 at 18:23
  • 1
    OK, we're moving along then. What if the source string is "ABCBDE" and the search string is "B". Do you want "A", "B", "CBDE", or "A", "B", "C", "B", "DE", or something else? – Eric Lippert Apr 23 '20 at 18:24
  • 1
    Does this answer your question? [Split a string by another string in C#](https://stackoverflow.com/questions/2245442/split-a-string-by-another-string-in-c-sharp) – Wyck Apr 23 '20 at 18:25
  • @EricLippert : "A","B", "CBDE" – Bokambo Apr 23 '20 at 18:30
  • 4
    Then it sounds like using the `Split` method but limiting it to a single split is the way to go. – Eric Lippert Apr 23 '20 at 18:42

4 Answers4

1

You could just consider "Money Laundering Rules" to be the delimiter. Then you can write

string[] result = watch.Split(new string[] { searchtext }, StringSplitOptions.None);

Then you can add the delimiter again

string result1 = result[0];
string result2 = searchtext + result[1];
Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
  • How to handle if search value is in middle, please see my updated post ? – – Bokambo Apr 23 '20 at 22:50
  • 1
    @user662285 I would suggest re-writing your post, your top part seems directly contradictory to what you wrote originally. If you don't want the split delimiter including, you can just use regular `Split`. And your comment answers suggest you do want the split delimiter, but as a third string. You can't have one code do three different things. – NetMage Apr 24 '20 at 00:15
  • @Oliver : Created a new post - https://stackoverflow.com/questions/61416510/string-split-with-specified-string-without-delimeter-with-text-in-middle – Bokambo Apr 24 '20 at 20:00
0

Use string.Split.

string text = "Bitcoin ATMs Highlight Flaws in EU Money Laundering Rules";
string searchtext = "Money Laundering Rules";
string[] fragments = text.Split(new string[] { searchtext }, StringSplitOptions.None);

fragments will equal:

[0] "Bitcoin ATMs Highlight Flaws in EU "
[1] ""

Everywhere there is a gap between consecutive array elements, your search string appears. e.g.:

string originaltext = string.Join(searchtext, fragments);

Extended Description of String.Split Behaviour

Here is a quick table of the behaviour of string.Split when passed a string.

| Input  | Split | Result Array       |
+--------+-------+--------------------+
| "ABC"  | "A"   | { "", "BC" }       |
| "ABC"  | "B"   | { "A", "C" }       |
| "ABC"  | "C"   | { "AB", "" }       |
| "ABC"  | "D"   | { "ABC" }          |
| "ABC"  | "ABC" | { "", "" }         |
| "ABBA" | "A"   | { "", "BB", "" }   |
| "ABBA" | "B"   | { "A", "", "A" }   |
| "AAA"  | "A"   | { "", "", "", "" } |
| "AAA"  | "AA"  | { "", "A" }        |

If you look at the table above, Every place there was a comma in the array (between two consecutive elements in the array), is a place that the split string was found.

If the string was not found, then the result array is only one element (the original string).

If the split string is found at the beginning of the input string, then an empty string is set as the first element of the result array to represent the beginning of the string. Similarly, if the split string is found at the end of the string, an empty string is set as the last element of the result array.

Also, an empty string is included between any consecutive occurrences of the search string in the input string.

In cases where there are ambiguous overlapping locations at which the string could be found in the input string: (e.g. splitting AAA on AA could be split as AA|A or A|AA - where AA is found at position 0 or position 1 in the input string) then the earlier location is used. (e.g. AA|A, resulting in { "", "A" } ).

Again, the invariant is that the original string can always be reconstructed by joining all the fragments and placing exactly one occurrence of the search text in between elements. The following will always be true:

string.Join(searchtext, fragments) == text

If you only want the first split...

You can merge all results after the first back together like this:

if (fragments.Length > 1) {
    fragments = new string[] { fragments[0], string.Join(searchtext, fragments.Skip(1)) };
}

... or a more efficient way using String.IndexOf

If you just want to find the first location of the search text string then use String.IndexOf to get the position of the first occurrence of the search text in the input string.

Here's a complete function you can use

private static bool TrySplitOnce(string text, string searchtext, out string beforetext, out string aftertext)
{
    int pos = text.IndexOf(searchtext);
    if (pos < 0) {
        // not found
        beforetext = null;
        aftertext = null;
        return false;
    } else {
        // found at position `pos`
        beforetext = text.Substring(0, pos); // may be ""
        aftertext = text.Substring(pos + searchtext.Length); // may be ""
        return true;
    }
}

You can use this to produce an array, if you like.

usage:

string text = "red or white or blue";
string searchtext = "or";
if (TrySplitOnce(text, searchtext, out string before, out string after)) {
    Console.WriteLine("{0}*{1}", before, after);
    // output:
    //     red * white or blue
    string[] array = new string[] { before, searchtext, after };
    // array == { "red ", "or", " white or blue" };
    Console.WriteLine(string.Join("|", array));
    // output:
    //     red |or| white or blue  
} else {
    Console.WriteLine("Not found");
}

output:

red * white or blue
red |or| white or blue
Wyck
  • 10,311
  • 6
  • 39
  • 60
  • How to handle if search value is in middle, please see my updated post ? – Bokambo Apr 23 '20 at 22:42
  • At user662285's request, I added more information about how to handle various cases such as when the search value is in the middle of the input string. But this is already all described in the documentation for [String.Split](https://learn.microsoft.com/en-us/dotnet/api/system.string.split?view=netframework-4.8#System_String_Split_System_String___System_StringSplitOptions_). – Wyck Apr 24 '20 at 14:48
  • Furthermore, after Eric helped reveal more details of the desired usage, I added the single-split approach using `String.IndexOf` and demonstrated usage of putting the search text back into the array as per user662285's comment. – Wyck Apr 24 '20 at 15:44
  • Your post helped me but i am facing issue - https://stackoverflow.com/questions/61416510/string-split-with-specified-string-without-delimeter-with-text-in-middle – Bokambo Apr 24 '20 at 20:00
0

You can write your own extension method for this:

// Splits s at sep with sep included at beginning of each part except first
// return no more than numParts parts
public static IEnumerable<string> SplitsBeforeInc(this string s, string sep, int numParts = Int32.MaxValue)
    => s.Split(new[] { sep }, numParts, StringSplitOptions.None).Select((p,i) => i > 0 ? sep+p : p);

And use it with:

foreach(var itemco in watch.SplitsBeforeInc(watch, serachetxt, 2))

Here is the same method in a non-LINQ version:

// Splits s at sep with sep included at beginning of each part except first
// return no more than numParts parts
public static IEnumerable<string> SplitsBeforeInc(this string s, string sep, int numParts = Int32.MaxValue) {
    var startPos = 0;
    var searchPos = 0;
    while (startPos < s.Length && --numParts > 0) {
        var sepPos = s.IndexOf(sep, searchPos);
        sepPos = sepPos < 0 ? s.Length : sepPos;
        yield return s.Substring(startPos, sepPos - startPos);
        startPos = sepPos;
        searchPos = sepPos+sep.Length;
    }
    if (startPos < s.Length)
        yield return s.Substring(startPos);
}
NetMage
  • 26,163
  • 3
  • 34
  • 55
0

You can try this

        string text = "Trio charged over alleged $100m money laundering syndicate at Merrylands, Guildford West";
        string searchtext = "charged over";
        searchtextPattern =  "(?=" + searchtext + ")";

        string[] fragments= Regex.Split(text, searchtextPattern);
        //fargments will have two elements here
        // fragments[0] - "Trio"
        // fragments[1] - "charged over alleged $100m money laundering syndicate at Merrylands, Guildford West"

now you can again split fragment which have search text i.e fragments[1] in this case. see code below

            var stringWithoutSearchText = fragments[1].Replace(searchtext, string.Empty);

you need to check whether each fragment contains search text or not. You can do that it your foreach loop on fragments. add below check over there

     foreach (var item in fragments)
     { 
        if (item.Contains(searchtext))
        { 
          string stringWithoutSearchText = item.Replace(searchtext, string.Empty);
        }
     }

Reference : https://stackoverflow.com/a/521172/8652887