diff --git a/Xledger.Collections.Test/TestImmArray.cs b/Xledger.Collections.Test/TestImmArray.cs index 0771ac7..3c6fe71 100644 --- a/Xledger.Collections.Test/TestImmArray.cs +++ b/Xledger.Collections.Test/TestImmArray.cs @@ -172,5 +172,16 @@ public void TestSpan() { } public record Employee(int Id, string Name, decimal Salary); + + [Fact] + public void TestToImmArrayWithFunc() { + var arr = Enumerable.Range(-1, 100).Select(i => $"{i}: {2*i}").ToArray(); + var imm = Enumerable.Range(-1, 100).ToImmArray(i => $"{i}: {2 * i}"); + Assert.Equal(arr.Length, imm.Length); + Assert.Equal("-1: -2", imm[0]); + for (int i = 0; i < imm.Length; ++i) { + Assert.Equal(arr[i], imm[i]); + } + } } diff --git a/Xledger.Collections.Test/TestImmSet.cs b/Xledger.Collections.Test/TestImmSet.cs index ced1dcc..b9a360d 100644 --- a/Xledger.Collections.Test/TestImmSet.cs +++ b/Xledger.Collections.Test/TestImmSet.cs @@ -107,6 +107,15 @@ public void TestNoOps() { Assert.ThrowsAny(() => iset.Remove(4)); Assert.ThrowsAny(() => ((System.Collections.ICollection)iset).CopyTo((Array)null, 0)); } + + [Fact] + public void TestSelect() { + var imm = Enumerable.Range(-10, 21).ToImmSet(Math.Abs); + Assert.Equal(11, imm.Count); + for (int i = 0; i < 10; ++i) { + Assert.Contains(i, (ISet)imm); + } + } } diff --git a/Xledger.Collections/Extensions.cs b/Xledger.Collections/Extensions.cs index e5caab7..31338bd 100644 --- a/Xledger.Collections/Extensions.cs +++ b/Xledger.Collections/Extensions.cs @@ -12,6 +12,16 @@ public static ImmArray ToImmArray(this IEnumerable xs) { }; } + public static ImmArray ToImmArray(this IEnumerable xs, Func selector) { + return xs switch { + null => ImmArray.Empty, + T[] arr => new ImmArray(ArrayOf(arr.Length, arr, selector)), + ICollection coll => new ImmArray(ArrayOf(coll.Count, coll, selector)), + IReadOnlyCollection roColl => new ImmArray(ArrayOf(roColl.Count, roColl, selector)), + _ => new ImmArray(ArrayOf(xs, selector)), + }; + } + #if NET public static ImmArray ToImmArray(this ReadOnlySpan xs) { return new ImmArray(xs.ToArray()); @@ -26,6 +36,13 @@ public static ImmSet ToImmSet(this IEnumerable xs) { }; } + public static ImmSet ToImmSet(this IEnumerable xs, Func selector) { + return xs switch { + null => ImmSet.Empty, + _ => new ImmSet(SetOf(xs, selector)), + }; + } + #if NET public static ImmSet ToImmSet(this ReadOnlySpan xs) { return new ImmSet(xs.ToArray()); @@ -64,6 +81,7 @@ Func selectVal _ => new ImmDict(xs.ToDictionary(selectKey, selectVal)), }; } + internal static T[] ArrayOf(T[] arr) { return (T[])arr.Clone(); } @@ -92,10 +110,32 @@ internal static T[] ArrayOf(IEnumerable xs) { return lst.ToArray(); } + internal static U[] ArrayOf(int n, IEnumerable xs, Func f) { + var arr = new U[n]; + var i = 0; + foreach (var x in xs) { + arr[i] = f(x); + ++i; + } + return arr; + } + + internal static U[] ArrayOf(IEnumerable xs, Func f) { + var lst = new List(); + foreach (var x in xs) { + lst.Add(f(x)); + } + return lst.ToArray(); + } + internal static HashSet SetOf(IEnumerable xs) { return new HashSet(xs); } + internal static HashSet SetOf(IEnumerable xs, Func f) { + return new HashSet(xs.Select(f)); + } + internal static Dictionary DictOf(IEnumerable> xs) { #if NET6_0_OR_GREATER return new Dictionary(xs, null);