Tổng quan về các phần mở rộng LINQ trong thư viện Ix.NET

Phần Mở Rộng Ix.NET

Bài viết này trình bày về các phương thức mở rộng trong thư viện Ix.NET, giúp cải thiện và thêm chức năng cho LINQ.

Buffer

Ix.NET Buffer Ix.NET BufferTest

Phương thức Buffer chia nguồn dữ liệu thành các khối theo kích thước và vị trí bắt đầu.

var ds = Enumerable.Range(0, 10);
var ketQua = ds.Buffer(3).ToList();
// ketQua.Count == 4
// ketQua[0] == { 0, 1, 2 }
// ketQua[1] == { 3, 4, 5 }
// ketQua[2] == { 6, 7, 8 }
// ketQua[3] == { 9 }
var ds = Enumerable.Range(0, 10);
var ketQua = ds.Buffer(5).ToList();
// ketQua.Count == 2
// ketQua[0] == { 0, 1, 2, 3, 4 }
// ketQua[1] == { 5, 6, 7, 8, 9 }
var ds = Enumerable.Empty<int>();
var ketQua = ds.Buffer(5).ToList();
// ketQua.Count == 0
var ds = Enumerable.Range(0, 10);
var ketQua = ds.Buffer(3, 2).ToList();
// ketQua.Count == 5
// ketQua[0] == { 0, 1, 2 }
// ketQua[1] == { 2, 3, 4 }
// ketQua[2] == { 4, 5, 6 }
// ketQua[3] == { 6, 7, 8 }
// ketQua[4] == { 8, 9 }

Case

Ix.NET Case Ix.NET CaseTest

Phương thức Case trả về một trong các Dictionary tùy thuộc vào kết quả của hàm callback.

var gt = 1;
var kyTu = 'd';
var ketQua = EnumerableEx.Case<int, char>(() => gt, new Dictionary<int, IEnumerable<char>>
{
    { 0, new[] { 'a' } },
    { 1, new[] { 'b' } },
    { 2, new[] { 'c' } },
    { 3, EnumerableEx.Defer(() => new[] { kyTu }) },
});
// ketQua.Single() == 'b'
// ketQua.Single() == 'b'
gt = 0;
// ketQua.Single() == 'a'
gt = 2;
// ketQua.Single() == 'c'
gt = 3;
// ketQua.Single() == 'd'
kyTu = 'e';
// ketQua.Single() == 'e'
gt = 4;
Assert.True(ketQua.IsEmpty());
var gt = 1;
var kyTu = 'd';
var ketQua = EnumerableEx.Case<int, char>(() => gt, new Dictionary<int, IEnumerable<char>>
{
    { 0, new[] { 'a' } },
    { 1, new[] { 'b' } },
    { 2, new[] { 'c' } },
    { 3, EnumerableEx.Defer(() => new[] { kyTu }) },
}, new[] { 'z' });
// ketQua.Single() == 'b'
// ketQua.Single() == 'b'
gt = 0;
// ketQua.Single() == 'a'
gt = 2;
// ketQua.Single() == 'c'
gt = 3;
// ketQua.Single() == 'd'
kyTu = 'e';
// ketQua.Single() == 'e'
gt = 4;
// ketQua.Single() == 'z'

Catch

Ix.NET Catch Ix.NET CatchTest

var ex = new MyException();
var ketQua = EnumerableEx.Throw<int>(ex).Catch<int, MyException>(e => { Assert.Same(ex, e); return new[] { 42 }; }).Single();
// ketQua == 42
var ex = new MyException();
var ketQua = EnumerableEx.Throw<int>(ex).Catch<int, Exception>(e => { Assert.Same(ex, e); return new[] { 42 }; }).Single();
// ketQua == 42
var ex = new MyException();
AssertThrows<MyException>(() =>
{
    EnumerableEx.Throw<int>(ex).Catch<int, InvalidOperationException>(e => { Assert.True(false); return new[] { 42 }; }).Single();
});
var ds = Enumerable.Range(0, 10);
var ketQua = ds.Catch<int, MyException>(e => { Assert.True(false); return new[] { 42 }; });
// ketQua == ds
var dsArr = new[] { Enumerable.Range(0, 5), Enumerable.Range(5, 5) };
var ketQua = EnumerableEx.Catch(dsArr);
// ketQua == Enumerable.Range(0, 5)
var dsArr = new[] { Enumerable.Range(0, 5), Enumerable.Range(5, 5) };
var ketQua = dsArr.Catch();
// ketQua == Enumerable.Range(0, 5)
var dsArr = new[] { Enumerable.Range(0, 5), Enumerable.Range(5, 5) };
var ketQua = dsArr[0].Catch(dsArr[1]);
// ketQua == Enumerable.Range(0, 5)

Concat

Ix.NET Concat Ix.NET ConcatTest

Phương thức Concat nối các dãy dữ liệu lại với nhau.

var ketQua = new[]
{
    new[] { 1, 2, 3 },
    new[] { 4, 5 }
}.Concat();
// ketQua == { 1, 2, 3, 4, 5 }
var i = 0;
var dsArr = Enumerable.Range(0, 3).Select(x => Enumerable.Range(0, x + 1)).Do(_ => ++i);
var ketQua = dsArr.Concat().Select(x => i + " - " + x).ToList();
/*
ketQua == {
    "1 - 0",
    "2 - 0",
    "2 - 1",
    "3 - 0",
    "3 - 1",
    "3 - 2",
}
*/

Create

Ix.NET Create Ix.NET CreateTest

Phương thức Create tạo ra một dãy dữ liệu sử dụng coroutine.

private static IEnumerator<int> MyEnumerator()
{
    yield return 1;
    yield return 2;
}
var kiemTra = false;
var ketQua = EnumerableEx.Create<int>(() =>
{
    kiemTra = true;
    return MyEnumerator();
});
// kiemTra == false
var e = ketQua.GetEnumerator();
// kiemTra == true
HasNext(e, 1);
HasNext(e, 2);
NoNext(e);
kiemTra = false;
var f = ((IEnumerable)ketQua).GetEnumerator();
// kiemTra == true
var ds = EnumerableEx.Create<int>(async yield =>
{
    var i = 0;
    while (i < 10)
    {
        await yield.Return(i++);
    }
});
var j = 0;
foreach (var phanTu in ds)
{
    // phanTu == j
    j++;
}
// j == 10

Defer

Ix.NET Defer Ix.NET DeferTest

Phương thức Defer tạo ra một dãy dữ liệu từ một hàm callback.

var i = 0;
var n = 5;
var ds = EnumerableEx.Defer(() =>
{
    i++;
    return Enumerable.Range(0, n);
});
// i == 0
// ds.ToList() == Enumerable.Range(0, n)
// i == 1
n = 3;
// ds.ToList() == Enumerable.Range(0, n)
// i == 2

Distinct / DistinctUntilChanged

Ix.NET Distinct / DistinctUntilChanged Ix.NET DistinctTest Ix.NET DistinctUntilChangedTest

Distinct loại bỏ các phần tử trùng lặp. DistinctUntilChanged loại bỏ các phần tử trùng lặp gần nhau.

var ketQua = Enumerable.Range(0, 10).Distinct(x => x % 5).ToList();
// ketQua == Enumerable.Range(0, 5)
private class MyEqualityComparer : IEqualityComparer<int>
{
    public bool Equals(int x, int y)
    {
        return x % 2 == y % 2;
    }

    public int GetHashCode(int obj)
    {
        return EqualityComparer<int>.Default.GetHashCode(obj % 2);
    }
}
var ketQua = Enumerable.Range(0, 10).Distinct(x => x % 5, new MyEqualityComparer()).ToList();
// ketQua == { 0, 1 }
var ketQua = new[] { 1, 2, 2, 3, 3, 3, 2, 2, 1 }.DistinctUntilChanged().ToList();
// ketQua == { 1, 2, 3, 2, 1 }

Do / DoWhile

Ix.NET Do / DoWhile Ix.NET DoTest Ix.NET DoWhileTest

Do thực thi một hàm khi duyệt qua các phần tử. DoWhile tạo một dãy mới bằng cách lặp lại các phần tử cho đến khi điều kiện không còn thỏa mãn.

var n = 0;
Enumerable.Range(0, 10).Do(x => n += x).ForEach(_ => { });
// n == 45
var n = 0;
Enumerable.Range(0, 10).Do(x => n += x, () => n *= 2).ForEach(_ => { });
// n == 90

Expand

Ix.NET Expand Ix.NET ExpandTest

Expand thực hiện các bước sau:

  1. Áp dụng hàm cho từng phần tử của nguồn dữ liệu, tạo ra các dãy con và kết nối chúng.
  2. Lặp lại quá trình này cho đến khi không còn phần tử nào.
var ketQua = new[] { 0 }.Expand(x => new[] { x + 1 }).Take(10).ToList();
// ketQua == Enumerable.Range(0, 10)
var ketQua = new[] { 3 }.Expand(x => Enumerable.Range(0, x)).ToList();
var ketQuaDuyet = new[] {
    3,
    0, 1, 2,
    0,
    0, 1,
    0
};
// ketQua == ketQuaDuyet

Finally

Ix.NET Finally Ix.NET FinallyTest

var ketThuc = false;
var ds = Enumerable.Range(0, 2).Finally(() => ketThuc = true);
// ketThuc == false
var e = ds.GetEnumerator();
// ketThuc == false
HasNext(e, 0);
// ketThuc == false
HasNext(e, 1);
// ketThuc == false
NoNext(e);
// ketThuc == true

ForEach

Ix.NET ForEach Ix.NET ForEachTest

ForEach duyệt qua dãy dữ liệu và áp dụng hàm cho từng phần tử.

var n = 0;
Enumerable.Range(5, 3).ForEach(x => n += x);
// n == 5 + 6 + 

Thẻ: IX.NET linq C# Dãy dữ liệu

Đăng vào ngày 21 tháng 6 lúc 17:52