The "classy" way to filter collections.
C# Batchfile
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.

README.md

Filter RimDev.Filter NuGet badge RimDev.Filter NuGet downloads

"the classy way to filter collections"

This library allows an IEnumerable to be filtered using either a typed or anonymous class.

Installation

Install the RimDev.Filter NuGet package.

Install-Package RimDev.Filter

Usage

using RimDev.Filter.Generic;
using RimDev.Filter.Range;

public class Person
{
    public Person(string firstName, int favoriteNumber)
    {
        FavoriteNumber = favoriteNumber;
        FirstName = firstName;
    }

    public int FavoriteNumber { get; set; }
    public string FirstName { get; set; }
}

var people = new List<Person>()
{
    new Person("John", 1),
    new Person("Tom", 2),
    new Person("Jane", 3),
    new Person("Sally", 4)
};

IEnumerable<Person> filteredPeople = null;

// returns just the first-record.
filteredPeople = people.Filter(new
{
    FirstName = "John"
});

// returns the first and second-record.
filteredPeople = people.Filter(new
{
    FirstName = new[] { "John", "Tom" }
});

// returns the second-record.
filteredPeople = people.Filter(new
{
    FavoriteNumber = Range.FromString<int>("(1,3)")
});

// returns the first three-records.
filteredPeople = people.Filter(new
{
    FavoriteNumber = Range.FromString<int>("[1,4)")
});

Range-type

This is a new type which allows an easy way to represent a range of values when filtering. An instance can either be created manually or via a helper which takes a string formatted using standard interval notation.

While any type is allowed as a range, only certain types will work when filtering:

  • byte
  • char
  • DateTime
  • decimal
  • double
  • float
  • int
  • long
  • sbyte
  • short
  • uint
  • ulong
  • ushort

Any other types will just silently get passed-over.

Usage

using RimDev.Filter.Range;
using RimDev.Filter.Range.Generic;

var range = new Range<int>()
{
    MinValue = 0,
    MaxValue = 10,
    IsMinInclusive = false,
    IsMaxInclusive = true
};

// or with helper.
var range = Range.FromString<int>("(0,10]");

Implicit casting

Instead of having to call the static-helper Range.FromString<T>, you can also leverage implicit casting support:

Range<int> range = "[1,5]";

// or...

// Type is Range<int>.
var range2 = (Range<int>)"[1,5]";

Open-ended support

Instead of having to specify both lower and upper-bound, you can truncate one of the two:

// x <= 5
var range = (Range<int>)"(,5]";

// range.MinValue.HasValue == false;

// or use Unicode

var range2 = (Range<int>)"(-∞,5]";
var range3 = (Range<int>)"[1,+∞)";

Short-syntax version

Some assumptions are made if enclosing-characters (i.e. [, (, ], )) are not used:

var range = (Range<int>)"123";

// range.MinValue == 123;
// range.MaxValue == 123;
// range.IsMinInclusive == true;
// range.IsMaxInclusive == true;

var range2 = (Range<int>)",456";

// range2.MinValue == null;
// range2.MaxValue == 456;
// range2.IsMinInclusive == true;
// range2.IsMaxInclusive == true;

var range3 = (Range<int>)"(123,";

// range3.MinValue == 123;
// range3.MaxValue == 123;
// range3.IsMinInclusive == false;
// range3.IsMaxInclusive == true;

Current limitations

  • The library currently only works with class-type collections.
  • Constant filter-value (i.e. non-enumerable or range) exceptions are trapped within the Filter call.

License

MIT

Contributing

Issue documentation and pull-requests are welcomed. This project follows the fork & pull model.