1
0
mirror of https://github.com/oliverbooth/X10D synced 2024-11-09 16:35:42 +00:00

feat: add IEnumerable<string>.Grep()

This commit is contained in:
Oliver Booth 2023-03-30 17:29:54 +01:00
parent f49188b428
commit d0f94a6493
No known key found for this signature in database
GPG Key ID: 20BEB9DC87961025
3 changed files with 130 additions and 0 deletions

View File

@ -34,6 +34,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- X10D: Added `IEnumerable<T>.MinMax()` and `IEnumerable<T>.MinMaxBy()`. (#72)
- X10D: Added `IEnumerable<T>.WhereNot(Func<T, bool>)`.
- X10D: Added `IEnumerable<T>.WhereNotNull()`.
- X10D: Added `IEnumerable<string>.Grep(string[, bool])`.
- X10D: Added `IList<T>.RemoveRange(Range)`.
- X10D: Added `IList<T>.Swap(IList<T>)`. (#62)
- X10D: Added `IReadOnlyList<T>.IndexOf(T[, int[, int]])`.

View File

@ -0,0 +1,57 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using X10D.Text;
namespace X10D.Tests.Text;
[TestClass]
public class EnumerableTests
{
[TestMethod]
public void Grep_ShouldFilterCorrectly_GivenPattern()
{
int year = DateTime.Now.Year;
var source = new[] {"Hello", "World", "String 123", $"The year is {year}"};
var expectedResult = new[] {"String 123", $"The year is {year}"};
const string pattern = /*lang=regex*/@"[0-9]+";
string[] actualResult = source.Grep(pattern).ToArray();
CollectionAssert.AreEqual(expectedResult, actualResult);
}
[TestMethod]
public void Grep_ShouldMatchUpperCase_GivenIgnoreCaseTrue()
{
int year = DateTime.Now.Year;
var source = new[] {"Hello", "WORLD", "String 123", $"The year is {year}"};
var expectedResult = new[] {"WORLD"};
const string pattern = /*lang=regex*/@"world";
string[] actualResult = source.Grep(pattern, true).ToArray();
CollectionAssert.AreEqual(expectedResult, actualResult);
}
[TestMethod]
public void Grep_ShouldNotMatchUpperCase_GivenIgnoreCaseFalse()
{
int year = DateTime.Now.Year;
var source = new[] {"Hello", "WORLD", "String 123", $"The year is {year}"};
const string pattern = /*lang=regex*/@"world";
string[] actualResult = source.Grep(pattern, false).ToArray();
Assert.AreEqual(0, actualResult.Length);
}
[TestMethod]
public void Grep_ShouldYieldNoElements_GivenNoMatchingStrings()
{
var source = new[] {"Hello", "World", "String"};
const string pattern = /*lang=regex*/@"[0-9]+";
string[] actualResult = source.Grep(pattern).ToArray();
Assert.AreEqual(0, actualResult.Length);
}
}

View File

@ -0,0 +1,72 @@
using System.Text.RegularExpressions;
namespace X10D.Text;
/// <summary>
/// Text-related extension methods for <see cref="IEnumerable{T}" />.
/// </summary>
public static class EnumerableExtensions
{
/// <summary>
/// Filters a sequence of strings by regular expression.
/// </summary>
/// <param name="source">The sequence of strings to filter.</param>
/// <param name="pattern">The regular expression pattern to use for matching.</param>
/// <returns>The filtered sequence.</returns>
public static IEnumerable<string> Grep(this IEnumerable<string> source, string pattern)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(source);
ArgumentNullException.ThrowIfNull(pattern);
#else
if (source is null)
{
throw new ArgumentNullException(nameof(source));
}
if (pattern is null)
{
throw new ArgumentNullException(nameof(pattern));
}
#endif
return Grep(source, pattern, false);
}
/// <summary>
/// Filters a sequence of strings by regular expression, optionally allowing to ignore casing.
/// </summary>
/// <param name="source">The sequence of strings to filter.</param>
/// <param name="pattern">The regular expression pattern to use for matching.</param>
/// <param name="ignoreCase">
/// <see langword="true" /> to ignore casing when matching; otherwise, <see langword="false" />.
/// </param>
/// <returns>The filtered sequence.</returns>
public static IEnumerable<string> Grep(this IEnumerable<string> source, string pattern, bool ignoreCase)
{
#if NET6_0_OR_GREATER
ArgumentNullException.ThrowIfNull(source);
ArgumentNullException.ThrowIfNull(pattern);
#else
if (source is null)
{
throw new ArgumentNullException(nameof(source));
}
if (pattern is null)
{
throw new ArgumentNullException(nameof(pattern));
}
#endif
var regex = new Regex(pattern, RegexOptions.Compiled | (ignoreCase ? RegexOptions.IgnoreCase : RegexOptions.None));
foreach (string item in source)
{
if (regex.IsMatch(item))
{
yield return item;
}
}
}
}