Skip to content

Commit de5a0bb

Browse files
committed
Add ToCompositeRangeExclusive.
Fixes #110
1 parent 9b8be29 commit de5a0bb

2 files changed

Lines changed: 232 additions & 2 deletions

File tree

CodeJam.Main.Tests/Ranges/CompositeRangeTests.cs

Lines changed: 125 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ namespace CodeJam.Ranges
2323
[SuppressMessage("ReSharper", "StringLiteralTypo")]
2424
public static class CompositeRangeTests
2525
{
26-
#region Parse helpers
26+
#region Parse helpers
2727
private static CompositeRange<T> ParseCompositeRange<T>(
2828
[NotNull] string value,
2929
Func<string, T> parseValueCallback)
@@ -76,7 +76,7 @@ private static CompositeRange<T, TKey> ParseCompositeRange<T, TKey>(
7676

7777
public static CompositeRange<int?, string> ParseCompositeKeyedRangeInt32([NotNull] string value) =>
7878
ParseCompositeRange(value, s => (int?)int.Parse(s, CultureInfo.InvariantCulture), s => s.IsNullOrEmpty() ? null : s);
79-
#endregion
79+
#endregion
8080

8181
[Test]
8282
public static void TestCompositeRangeUseCase()
@@ -588,6 +588,129 @@ public static void TestCompositeRangeWithValues()
588588
AreEqual(compositeRange4, compositeRange.WithoutKeys());
589589
}
590590

591+
[Test]
592+
public static void TestCompositeRangeExclusiveWithOrWithoutKeys()
593+
{
594+
var compositeRange = Enumerable
595+
.Range(1, 2)
596+
.ToCompositeRangeExclusive(i => i - 1, i => i + 1);
597+
AreEqual(compositeRange.ToString(), "(0..3): { '1':(0..2); '2':(1..3) }");
598+
599+
var compositeRange2 = compositeRange.WithKeys(i => "A" + i);
600+
AreEqual(compositeRange2.ToString(), "(0..3): { 'A1':(0..2); 'A2':(1..3) }");
601+
602+
var compositeRange3 = compositeRange2.WithoutKeys();
603+
AreEqual(compositeRange3.ToString(), "(0..3): { (0..2); (1..3) }");
604+
605+
var compositeRange4 = compositeRange3.WithKeys("A");
606+
AreEqual(compositeRange4.ToString(), "(0..3): { 'A':(0..2); 'A':(1..3) }");
607+
608+
var compositeRange5 = compositeRange4.WithKeys("B");
609+
AreEqual(compositeRange5.ToString(), "(0..3): { 'B':(0..2); 'B':(1..3) }");
610+
}
611+
612+
[Test]
613+
public static void TestCompositeRangeExclusiveWithValues()
614+
{
615+
var compositeRange = Enumerable
616+
.Range(1, 2)
617+
.ToCompositeRangeExclusive(i => i - 1, i => i + 1);
618+
AreEqual(compositeRange.ToString(), "(0..3): { '1':(0..2); '2':(1..3) }");
619+
620+
var compositeRange2 = compositeRange.WithValues(i => "A" + i);
621+
AreEqual(compositeRange2.ToString(), "(A0..A3): { '1':(A0..A2); '2':(A1..A3) }");
622+
623+
var compositeRange3 = compositeRange2.WithValues(i => i, i => "B" + i.Substring(1));
624+
AreEqual(compositeRange3.ToString(), "(A0..B3): { '1':(A0..B2); '2':(A1..B3) }");
625+
626+
var compositeRange4 = compositeRange3.WithoutKeys().WithValues(i => int.Parse(i.Substring(1)));
627+
AreEqual(compositeRange4.ToString(), "(0..3): { (0..2); (1..3) }");
628+
629+
AreEqual(compositeRange4, compositeRange.WithoutKeys());
630+
}
631+
632+
[Test]
633+
public static void TestCompositeRangeExclusiveFromWithOrWithoutKeys()
634+
{
635+
var compositeRange = Enumerable
636+
.Range(1, 2)
637+
.ToCompositeRangeExclusiveFrom(i => i - 1, i => i + 1);
638+
AreEqual(compositeRange.ToString(), "(0..3]: { '1':(0..2]; '2':(1..3] }");
639+
640+
var compositeRange2 = compositeRange.WithKeys(i => "A" + i);
641+
AreEqual(compositeRange2.ToString(), "(0..3]: { 'A1':(0..2]; 'A2':(1..3] }");
642+
643+
var compositeRange3 = compositeRange2.WithoutKeys();
644+
AreEqual(compositeRange3.ToString(), "(0..3]: { (0..2]; (1..3] }");
645+
646+
var compositeRange4 = compositeRange3.WithKeys("A");
647+
AreEqual(compositeRange4.ToString(), "(0..3]: { 'A':(0..2]; 'A':(1..3] }");
648+
649+
var compositeRange5 = compositeRange4.WithKeys("B");
650+
AreEqual(compositeRange5.ToString(), "(0..3]: { 'B':(0..2]; 'B':(1..3] }");
651+
}
652+
653+
[Test]
654+
public static void TestCompositeRangeExclusiveFromWithValues()
655+
{
656+
var compositeRange = Enumerable
657+
.Range(1, 2)
658+
.ToCompositeRangeExclusiveFrom(i => i - 1, i => i + 1);
659+
AreEqual(compositeRange.ToString(), "(0..3]: { '1':(0..2]; '2':(1..3] }");
660+
661+
var compositeRange2 = compositeRange.WithValues(i => "A" + i);
662+
AreEqual(compositeRange2.ToString(), "(A0..A3]: { '1':(A0..A2]; '2':(A1..A3] }");
663+
664+
var compositeRange3 = compositeRange2.WithValues(i => i, i => "B" + i.Substring(1));
665+
AreEqual(compositeRange3.ToString(), "(A0..B3]: { '1':(A0..B2]; '2':(A1..B3] }");
666+
667+
var compositeRange4 = compositeRange3.WithoutKeys().WithValues(i => int.Parse(i.Substring(1)));
668+
AreEqual(compositeRange4.ToString(), "(0..3]: { (0..2]; (1..3] }");
669+
670+
AreEqual(compositeRange4, compositeRange.WithoutKeys());
671+
}
672+
673+
[Test]
674+
public static void TestCompositeRangeExclusiveToWithOrWithoutKeys()
675+
{
676+
var compositeRange = Enumerable
677+
.Range(1, 2)
678+
.ToCompositeRangeExclusiveTo(i => i - 1, i => i + 1);
679+
AreEqual(compositeRange.ToString(), "[0..3): { '1':[0..2); '2':[1..3) }");
680+
681+
var compositeRange2 = compositeRange.WithKeys(i => "A" + i);
682+
AreEqual(compositeRange2.ToString(), "[0..3): { 'A1':[0..2); 'A2':[1..3) }");
683+
684+
var compositeRange3 = compositeRange2.WithoutKeys();
685+
AreEqual(compositeRange3.ToString(), "[0..3): { [0..2); [1..3) }");
686+
687+
var compositeRange4 = compositeRange3.WithKeys("A");
688+
AreEqual(compositeRange4.ToString(), "[0..3): { 'A':[0..2); 'A':[1..3) }");
689+
690+
var compositeRange5 = compositeRange4.WithKeys("B");
691+
AreEqual(compositeRange5.ToString(), "[0..3): { 'B':[0..2); 'B':[1..3) }");
692+
}
693+
694+
[Test]
695+
public static void TestCompositeRangeExclusiveToWithValues()
696+
{
697+
var compositeRange = Enumerable
698+
.Range(1, 2)
699+
.ToCompositeRangeExclusiveTo(i => i - 1, i => i + 1);
700+
AreEqual(compositeRange.ToString(), "[0..3): { '1':[0..2); '2':[1..3) }");
701+
702+
var compositeRange2 = compositeRange.WithValues(i => "A" + i);
703+
AreEqual(compositeRange2.ToString(), "[A0..A3): { '1':[A0..A2); '2':[A1..A3) }");
704+
705+
var compositeRange3 = compositeRange2.WithValues(i => i, i => "B" + i.Substring(1));
706+
AreEqual(compositeRange3.ToString(), "[A0..B3): { '1':[A0..B2); '2':[A1..B3) }");
707+
708+
var compositeRange4 = compositeRange3.WithoutKeys().WithValues(i => int.Parse(i.Substring(1)));
709+
AreEqual(compositeRange4.ToString(), "[0..3): { [0..2); [1..3) }");
710+
711+
AreEqual(compositeRange4, compositeRange.WithoutKeys());
712+
}
713+
591714
[Test]
592715
[TestCase(
593716
"∅",

CodeJam.Main/Ranges/[RangeExtensions]/CompositeRangeExtensions.cs

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,113 @@ public static CompositeRange<T, TKey> ToCompositeRange<TSource, T, TKey>(
4747
.ToCompositeRange();
4848
#endregion
4949

50+
#region ToCompositeRangeExclusive
51+
/// <summary>Converts sequence of elements to the composite range.</summary>
52+
/// <typeparam name="T">The type of the range values.</typeparam>
53+
/// <typeparam name="TKey">The type of the range key</typeparam>
54+
/// <param name="source">Original collection.</param>
55+
/// <param name="fromValueSelector">Callback to obtain a value for the From boundary.</param>
56+
/// <param name="toValueSelector">Callback to obtain a value for the To boundary.</param>
57+
/// <returns>A new composite range with keys filled from the original collection.</returns>
58+
[Pure]
59+
public static CompositeRange<T, TKey> ToCompositeRangeExclusive<T, TKey>(
60+
[NotNull] this IEnumerable<TKey> source,
61+
[NotNull, InstantHandle] Func<TKey, T> fromValueSelector,
62+
[NotNull, InstantHandle] Func<TKey, T> toValueSelector) =>
63+
source
64+
.Select(s => Range.CreateExclusive(fromValueSelector(s), toValueSelector(s), s))
65+
.ToCompositeRange();
66+
67+
/// <summary>Converts sequence of elements to the composite range.</summary>
68+
/// <typeparam name="TSource">The type of the values in original collection.</typeparam>
69+
/// <typeparam name="T">The type of the range values.</typeparam>
70+
/// <typeparam name="TKey">The type of the range key</typeparam>
71+
/// <param name="source">Original collection.</param>
72+
/// <param name="fromValueSelector">Callback to obtain a value for the From boundary.</param>
73+
/// <param name="toValueSelector">Callback to obtain a value for the To boundary.</param>
74+
/// <param name="keySelector">Callback to obtain a value for the range key.</param>
75+
/// <returns>A new composite range with keys filled from the original collection.</returns>
76+
[Pure]
77+
public static CompositeRange<T, TKey> ToCompositeRangeExclusive<TSource, T, TKey>(
78+
[NotNull] this IEnumerable<TSource> source,
79+
[NotNull, InstantHandle] Func<TSource, T> fromValueSelector,
80+
[NotNull, InstantHandle] Func<TSource, T> toValueSelector,
81+
[NotNull, InstantHandle] Func<TSource, TKey> keySelector) =>
82+
source
83+
.Select(s => Range.CreateExclusive(fromValueSelector(s), toValueSelector(s), keySelector(s)))
84+
.ToCompositeRange();
85+
86+
/// <summary>Converts sequence of elements to the composite range.</summary>
87+
/// <typeparam name="T">The type of the range values.</typeparam>
88+
/// <typeparam name="TKey">The type of the range key</typeparam>
89+
/// <param name="source">Original collection.</param>
90+
/// <param name="fromValueSelector">Callback to obtain a value for the From boundary.</param>
91+
/// <param name="toValueSelector">Callback to obtain a value for the To boundary.</param>
92+
/// <returns>A new composite range with keys filled from the original collection.</returns>
93+
[Pure]
94+
public static CompositeRange<T, TKey> ToCompositeRangeExclusiveFrom<T, TKey>(
95+
[NotNull] this IEnumerable<TKey> source,
96+
[NotNull, InstantHandle] Func<TKey, T> fromValueSelector,
97+
[NotNull, InstantHandle] Func<TKey, T> toValueSelector) =>
98+
source
99+
.Select(s => Range.CreateExclusiveFrom(fromValueSelector(s), toValueSelector(s), s))
100+
.ToCompositeRange();
101+
102+
/// <summary>Converts sequence of elements to the composite range.</summary>
103+
/// <typeparam name="TSource">The type of the values in original collection.</typeparam>
104+
/// <typeparam name="T">The type of the range values.</typeparam>
105+
/// <typeparam name="TKey">The type of the range key</typeparam>
106+
/// <param name="source">Original collection.</param>
107+
/// <param name="fromValueSelector">Callback to obtain a value for the From boundary.</param>
108+
/// <param name="toValueSelector">Callback to obtain a value for the To boundary.</param>
109+
/// <param name="keySelector">Callback to obtain a value for the range key.</param>
110+
/// <returns>A new composite range with keys filled from the original collection.</returns>
111+
[Pure]
112+
public static CompositeRange<T, TKey> ToCompositeRangeExclusiveFrom<TSource, T, TKey>(
113+
[NotNull] this IEnumerable<TSource> source,
114+
[NotNull, InstantHandle] Func<TSource, T> fromValueSelector,
115+
[NotNull, InstantHandle] Func<TSource, T> toValueSelector,
116+
[NotNull, InstantHandle] Func<TSource, TKey> keySelector) =>
117+
source
118+
.Select(s => Range.CreateExclusiveFrom(fromValueSelector(s), toValueSelector(s), keySelector(s)))
119+
.ToCompositeRange();
120+
121+
/// <summary>Converts sequence of elements to the composite range.</summary>
122+
/// <typeparam name="T">The type of the range values.</typeparam>
123+
/// <typeparam name="TKey">The type of the range key</typeparam>
124+
/// <param name="source">Original collection.</param>
125+
/// <param name="fromValueSelector">Callback to obtain a value for the From boundary.</param>
126+
/// <param name="toValueSelector">Callback to obtain a value for the To boundary.</param>
127+
/// <returns>A new composite range with keys filled from the original collection.</returns>
128+
[Pure]
129+
public static CompositeRange<T, TKey> ToCompositeRangeExclusiveTo<T, TKey>(
130+
[NotNull] this IEnumerable<TKey> source,
131+
[NotNull, InstantHandle] Func<TKey, T> fromValueSelector,
132+
[NotNull, InstantHandle] Func<TKey, T> toValueSelector) =>
133+
source
134+
.Select(s => Range.CreateExclusiveTo(fromValueSelector(s), toValueSelector(s), s))
135+
.ToCompositeRange();
136+
137+
/// <summary>Converts sequence of elements to the composite range.</summary>
138+
/// <typeparam name="TSource">The type of the values in original collection.</typeparam>
139+
/// <typeparam name="T">The type of the range values.</typeparam>
140+
/// <typeparam name="TKey">The type of the range key</typeparam>
141+
/// <param name="source">Original collection.</param>
142+
/// <param name="fromValueSelector">Callback to obtain a value for the From boundary.</param>
143+
/// <param name="toValueSelector">Callback to obtain a value for the To boundary.</param>
144+
/// <param name="keySelector">Callback to obtain a value for the range key.</param>
145+
/// <returns>A new composite range with keys filled from the original collection.</returns>
146+
[Pure]
147+
public static CompositeRange<T, TKey> ToCompositeRangeExclusiveTo<TSource, T, TKey>(
148+
[NotNull] this IEnumerable<TSource> source,
149+
[NotNull, InstantHandle] Func<TSource, T> fromValueSelector,
150+
[NotNull, InstantHandle] Func<TSource, T> toValueSelector,
151+
[NotNull, InstantHandle] Func<TSource, TKey> keySelector) =>
152+
source
153+
.Select(s => Range.CreateExclusiveTo(fromValueSelector(s), toValueSelector(s), keySelector(s)))
154+
.ToCompositeRange();
155+
#endregion
156+
50157
#region ToCompositeRangeFrom & ToCompositeRangeTo
51158
/// <summary>
52159
/// Converts sequence of elements to the composite range using only From boundary.

0 commit comments

Comments
 (0)