diff --git a/src/ByteDev.Strings/StringExtensions.cs b/src/ByteDev.Strings/StringExtensions.cs
index 0a79686..1b8d9e2 100644
--- a/src/ByteDev.Strings/StringExtensions.cs
+++ b/src/ByteDev.Strings/StringExtensions.cs
@@ -223,5 +223,35 @@ public static string InsertBeforeUpperCase(this string source, string delimiter)
return sb.ToString();
}
+
+ ///
+ /// Extracts the string between the specified start and end string.
+ /// e.g. for "The quick brown fox jumps over the lazy dog", the string between "quick" and "jumps" is " brown fox ".
+ /// If there are multiple instances of a start or end string, it will use the first instance.
+ /// An empty string will be returned if no matches were found.
+ ///
+ /// String to perform the operation on.
+ /// The start string to find
+ /// The end string to find after the startString
+ /// The string comparison to use (defaults to StringComparison.OrdinalIgnoreCase)
+ /// The string in between startString and endString, or empty string if not found
+ public static string ExtractStringBetween(this string source, string startString, string endString, StringComparison stringComparison = StringComparison.OrdinalIgnoreCase)
+ {
+ if (string.IsNullOrEmpty(source) || string.IsNullOrEmpty(startString) || string.IsNullOrEmpty(endString))
+ return string.Empty;
+
+ var extractedString = string.Empty;
+ var startIndex = source.IndexOf(startString, stringComparison);
+
+ if (startIndex > -1)
+ {
+ startIndex += startString.Length;
+ var endIndex = source.IndexOf(endString, startIndex, stringComparison);
+ if (endIndex > -1)
+ extractedString = source.SafeSubstring(startIndex, endIndex - startIndex);
+ }
+
+ return extractedString;
+ }
}
}
\ No newline at end of file
diff --git a/src/ByteDev.Strings/StringToExtensions.cs b/src/ByteDev.Strings/StringToExtensions.cs
index 65fa888..f10a97e 100644
--- a/src/ByteDev.Strings/StringToExtensions.cs
+++ b/src/ByteDev.Strings/StringToExtensions.cs
@@ -320,5 +320,31 @@ public static MemoryStream ToMemoryStream(this string source, Encoding encoding)
return new MemoryStream(bytes);
}
+
+ ///
+ /// Returns the string as a sequence with each value determined by the specified char delimiter, and converted to the specified type.
+ ///
+ /// The type to convert each item into.
+ /// The string to perform this operation on.
+ /// Value delimiter.
+ /// True trim each value; false do nothing.
+ /// Collection of values; otherwise empty. Throws exception if values cannot be converted.
+ public static IEnumerable ToConvertedSequence(this string sourceString, char delimiter = ',', bool trimValues = false)
+ where T : struct, IConvertible
+ {
+ if (string.IsNullOrEmpty(sourceString))
+ return Enumerable.Empty();
+
+ try
+ {
+ IEnumerable stringValues = sourceString.ToSequence(delimiter, trimValues);
+
+ return stringValues.Select(stringValue => (T)Convert.ChangeType(stringValue, typeof(T)));
+ }
+ catch (Exception)
+ {
+ return Enumerable.Empty();
+ }
+ }
}
}
\ No newline at end of file
diff --git a/tests/ByteDev.Strings.UnitTests/StringExtensionsTests.cs b/tests/ByteDev.Strings.UnitTests/StringExtensionsTests.cs
index 29781ff..501a0e3 100644
--- a/tests/ByteDev.Strings.UnitTests/StringExtensionsTests.cs
+++ b/tests/ByteDev.Strings.UnitTests/StringExtensionsTests.cs
@@ -561,5 +561,49 @@ public void WhenHasUpperCase_ThenReturnString(string sut, string expected)
Assert.That(result, Is.EqualTo(expected));
}
}
+
+ [TestFixture]
+ public class ExtractStringBetween
+ {
+ [TestCase(null)]
+ [TestCase("")]
+ public void WhenSourceIsNullOrEmpty_ThenReturnEmptyString(string source)
+ {
+ var result = source.ExtractStringBetween("test1", "test2");
+
+ Assert.That(result, Is.EqualTo(string.Empty));
+ }
+
+ [TestCase("The quick brown fox jumps over the lazy dog", "quick1", "jumps")]
+ [TestCase("The quick brown fox jumps over the lazy dog", "the", "not found")]
+ public void WhenIsNotAMatchingSearch_ThenReturnEmptyString(string source, string startString, string endString)
+ {
+ var result = source.ExtractStringBetween(startString, endString);
+
+ Assert.That(result, Is.EqualTo(string.Empty));
+ }
+
+ [TestCase("The quick brown fox jumps over the lazy dog", "quick", "jumps", " brown fox ")]
+ [TestCase("The quick brown fox jumps over the lazy dog", "the", "dog", " quick brown fox jumps over the lazy ")]
+ [TestCase("The quick brown fox jumps over the lazy dog", "lazy", "dog", " ")]
+ [TestCase("My test string", "", "", "My test string")]
+ [TestCase("My test string", "();
+
+ Assert.IsNotNull(result);
+ Assert.That(result.Count(), Is.EqualTo(0));
+ }
+
+ [TestCase("1")]
+ [TestCase("489")]
+ [TestCase("2147483647")]
+ public void WhenDoesNotContainDelimiter_ThenReturnListWithOneValue(string sut)
+ {
+ var result = sut.ToConvertedSequence();
+
+ Assert.IsNotNull(result);
+ var resultAsList = result.ToList();
+ Assert.That(resultAsList.Count, Is.EqualTo(1));
+ Assert.That(resultAsList[0], Is.EqualTo(Convert.ToInt32(sut)));
+ }
+
+ [TestCase("1,444,44", ',')]
+ [TestCase("89,092,7,9", ',')]
+ [TestCase("0:7", ':')]
+ [TestCase("8?99?5432?900", '?')]
+ public void WhenContainsDelimiter_ThenReturnListWithValues(string sut, char delimiter)
+ {
+ var expected = sut.Split(delimiter).Select(s => Convert.ToInt64(s));
+ var result = sut.ToConvertedSequence(delimiter);
+
+ Assert.IsNotNull(result);
+ Assert.That(result, Is.EqualTo(expected));
+ }
+
+ [TestCase("abc", ',')]
+ [TestCase("1,444,44", ':')]
+ [TestCase("0:7", ',')]
+ public void WhenInvalidValues_ThenThrowException(string sut, char delimiter)
+ {
+ Assert.Throws(() => sut.ToConvertedSequence(delimiter).ToList(), "Input string was not in a correct format.");
+ }
+ }
}
}
\ No newline at end of file