Skip to content

Commit

Permalink
Fixed issues with max() and min()
Browse files Browse the repository at this point in the history
  • Loading branch information
davidnmbond committed Jun 21, 2024
1 parent 1b84004 commit 2498767
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 27 deletions.
28 changes: 27 additions & 1 deletion PanoramicData.NCalcExtensions.Test/MaxTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,38 @@ public class MaxTests
[InlineData("1.1, null, 2", 2)]
[InlineData("null, null, null", null)]

public void Max_OfNumbers_ReturnsExpectedValue(string values, object? expectedOutput)
public void Max_OfListOfNullableDoubles_ReturnsExpectedValue(string values, object? expectedOutput)
{
var expression = new ExtendedExpression($"max(listOf('double?', {values}), 'x', 'x')");
expression.Evaluate().Should().BeEquivalentTo(expectedOutput);
}

[Theory]
[InlineData("1, 2, 3", 3)]
[InlineData("3, 2, 1", 3)]
[InlineData("1, 3, 2", 3)]
[InlineData("1, 1, 1", 1)]
[InlineData("1, 1, 2", 2)]

public void Max_OfListNumbers_WithLambda_ReturnsExpectedValue(string values, int expectedOutput)
{
var expression = new ExtendedExpression($"max(list({values}), 'x', 'x')");
expression.Evaluate().Should().BeEquivalentTo(expectedOutput);
}

[Theory]
[InlineData("1, 2, 3", 3)]
[InlineData("3, 2, 1", 3)]
[InlineData("1, 3, 2", 3)]
[InlineData("1, 1, 1", 1)]
[InlineData("1, 1, 2", 2)]

public void Max_OfListNumbers_WithIEnumerable_ReturnsExpectedValue(string values, int expectedOutput)
{
var expression = new ExtendedExpression($"max(list({values}))");
expression.Evaluate().Should().BeEquivalentTo(expectedOutput);
}

[Theory]
[InlineData("'1', '2', '3'", "3")]
[InlineData("'3', '2', '1'", "3")]
Expand Down
26 changes: 26 additions & 0 deletions PanoramicData.NCalcExtensions.Test/MinTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,32 @@ public void Min_OfNumbers_ReturnsExpectedValue(string values, object? expectedOu
expression.Evaluate().Should().BeEquivalentTo(expectedOutput);
}

[Theory]
[InlineData("1, 2, 3", 1)]
[InlineData("3, 2, 1", 1)]
[InlineData("1, 3, 2", 1)]
[InlineData("1, 1, 1", 1)]
[InlineData("1, 1, 2", 1)]

public void Min_OfListNumbers_WithLambda_ReturnsExpectedValue(string values, int expectedOutput)
{
var expression = new ExtendedExpression($"min(list({values}), 'x', 'x')");
expression.Evaluate().Should().BeEquivalentTo(expectedOutput);
}

[Theory]
[InlineData("1, 2, 3", 1)]
[InlineData("3, 2, 1", 1)]
[InlineData("1, 3, 2", 1)]
[InlineData("1, 1, 1", 1)]
[InlineData("1, 1, 2", 1)]

public void Min_OfListNumbers_WithIEnumerable_ReturnsExpectedValue(string values, int expectedOutput)
{
var expression = new ExtendedExpression($"min(list({values}))");
expression.Evaluate().Should().BeEquivalentTo(expectedOutput);
}

[Theory]
[InlineData("'1', '2', '3'", "1")]
[InlineData("'3', '2', '1'", "1")]
Expand Down
38 changes: 24 additions & 14 deletions PanoramicData.NCalcExtensions/Extensions/Max.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,30 @@
using System.Collections.Generic;
using System.Collections;
using System.Collections.Generic;

namespace PanoramicData.NCalcExtensions.Extensions;

internal static class Max
{
internal static void Evaluate(FunctionArgs functionArgs)
{
var originalList = functionArgs.Parameters[0].Evaluate();
var originalListUntyped = functionArgs.Parameters[0].Evaluate();

if (originalListUntyped is null)
{
functionArgs.Result = null;
return;
}

var originalList = originalListUntyped as IEnumerable ?? throw new FormatException($"First {ExtensionFunction.Max} parameter must be an IEnumerable.");

if (functionArgs.Parameters.Length == 1)
{
functionArgs.Result = originalList switch
{
null => null,
IEnumerable<byte> list => list.Cast<int>().Max(),
IEnumerable<byte> list => list.Max(),
IEnumerable<byte?> list => list.DefaultIfEmpty(null).Max(),
IEnumerable<short> list => list.Cast<int>().Max(),
IEnumerable<short> list => list.Max(),
IEnumerable<short?> list => list.DefaultIfEmpty(null).Max(),
IEnumerable<int> list => list.Max(),
IEnumerable<int?> list => list.DefaultIfEmpty(null).Max(),
Expand All @@ -30,7 +39,7 @@ internal static void Evaluate(FunctionArgs functionArgs)
IEnumerable<string?> list => list.DefaultIfEmpty(null).Max(),
IEnumerable<object?> list when list.All(x => x is string or null) => list.DefaultIfEmpty(null).Max(x => x as string),
IEnumerable<object?> list => GetMax(list),
_ => throw new FormatException($"First {ExtensionFunction.Max} parameter must be an IEnumerable of a numeric or string type if only on parameter is present.")
_ => throw new FormatException($"First {ExtensionFunction.Max} parameter must be an IEnumerable of a numeric or string type if only one parameter is present.")
};

return;
Expand All @@ -46,10 +55,10 @@ internal static void Evaluate(FunctionArgs functionArgs)

functionArgs.Result = originalList switch
{
IEnumerable<byte> list => list.Cast<int>().Max(value => (int?)lambda.Evaluate(value)),
IEnumerable<byte?> list => list.Cast<int>().Max(value => (int?)lambda.Evaluate(value)),
IEnumerable<short> list => list.Cast<int>().Max(value => (int?)lambda.Evaluate(value)),
IEnumerable<short?> list => list.Cast<int>().Max(value => (int?)lambda.Evaluate(value)),
IEnumerable<byte> list => list.Max(value => (int?)lambda.Evaluate(value)),
IEnumerable<byte?> list => list.Max(value => (int?)lambda.Evaluate(value)),
IEnumerable<short> list => list.Max(value => (int?)lambda.Evaluate(value)),
IEnumerable<short?> list => list.Max(value => (int?)lambda.Evaluate(value)),
IEnumerable<int> list => list.Max(value => (int?)lambda.Evaluate(value)),
IEnumerable<int?> list => list.Max(value => (int?)lambda.Evaluate(value)),
IEnumerable<long> list => list.Max(value => (long?)lambda.Evaluate(value)),
Expand All @@ -61,14 +70,15 @@ internal static void Evaluate(FunctionArgs functionArgs)
IEnumerable<decimal> list => list.Max(value => (decimal?)lambda.Evaluate(value)),
IEnumerable<decimal?> list => list.Max(value => (decimal?)lambda.Evaluate(value)),
IEnumerable<string?> list => list.Max(value => (string?)lambda.Evaluate(value)),
_ => throw new FormatException($"First {ExtensionFunction.Max} parameter must be an IEnumerable of a numeric type.")
IEnumerable<object?> list => GetMax(list.Select(value => lambda.Evaluate(value))),
_ => throw new FormatException($"First {ExtensionFunction.Max} parameter must be an IEnumerable of a string or numeric type when processing as a lambda.")
};

}

private static double GetMax(IEnumerable<object?> objectList)
{
double max = 0;
var max = double.NegativeInfinity;
foreach (var item in objectList)
{
var thisOne = item switch
Expand All @@ -84,12 +94,12 @@ private static double GetMax(IEnumerable<object?> objectList)
{
JTokenType.Float => jValue.Value<float>(),
JTokenType.Integer => jValue.Value<int>(),
_ => throw new FormatException($"Found unsupported JToken type '{jValue.Type}' when completing sum.")
_ => throw new FormatException($"Found unsupported JToken type '{jValue.Type}' when completing max.")
},
null => 0,
_ => throw new FormatException($"Found unsupported type '{item?.GetType().Name}' when completing sum.")
_ => throw new FormatException($"Found unsupported type '{item?.GetType().Name}' when completing max.")
};
if (thisOne < max)
if (thisOne > max)
{
max = thisOne;
}
Expand Down
35 changes: 23 additions & 12 deletions PanoramicData.NCalcExtensions/Extensions/Min.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,30 @@
using System.Collections.Generic;
using System.Collections;
using System.Collections.Generic;

namespace PanoramicData.NCalcExtensions.Extensions;

internal static class Min
{
internal static void Evaluate(FunctionArgs functionArgs)
{
var originalList = functionArgs.Parameters[0].Evaluate();
var originalListUntyped = functionArgs.Parameters[0].Evaluate();

if (originalListUntyped is null)
{
functionArgs.Result = null;
return;
}

var originalList = originalListUntyped as IEnumerable ?? throw new FormatException($"First {ExtensionFunction.Min} parameter must be an IEnumerable.");

if (functionArgs.Parameters.Length == 1)
{
functionArgs.Result = originalList switch
{
null => null,
IEnumerable<byte> list => list.Cast<int>().Min(),
IEnumerable<byte> list => list.Min(),
IEnumerable<byte?> list => list.DefaultIfEmpty(null).Min(),
IEnumerable<short> list => list.Cast<int>().Min(),
IEnumerable<short> list => list.Min(),
IEnumerable<short?> list => list.DefaultIfEmpty(null).Min(),
IEnumerable<int> list => list.Min(),
IEnumerable<int?> list => list.DefaultIfEmpty(null).Min(),
Expand All @@ -32,6 +41,7 @@ internal static void Evaluate(FunctionArgs functionArgs)
IEnumerable<object?> list => GetMin(list),
_ => throw new FormatException($"First {ExtensionFunction.Min} parameter must be an IEnumerable of a numeric or string type if only one parameter is present.")
};

return;
}

Expand All @@ -45,10 +55,10 @@ internal static void Evaluate(FunctionArgs functionArgs)

functionArgs.Result = originalList switch
{
IEnumerable<byte> list => list.Cast<int>().Min(value => (int?)lambda.Evaluate(value)),
IEnumerable<byte?> list => list.Cast<int>().Min(value => (int?)lambda.Evaluate(value)),
IEnumerable<short> list => list.Cast<int>().Min(value => (int?)lambda.Evaluate(value)),
IEnumerable<short?> list => list.Cast<int>().Min(value => (int?)lambda.Evaluate(value)),
IEnumerable<byte> list => list.Min(value => (int?)lambda.Evaluate(value)),
IEnumerable<byte?> list => list.Min(value => (int?)lambda.Evaluate(value)),
IEnumerable<short> list => list.Min(value => (int?)lambda.Evaluate(value)),
IEnumerable<short?> list => list.Min(value => (int?)lambda.Evaluate(value)),
IEnumerable<int> list => list.Min(value => (int?)lambda.Evaluate(value)),
IEnumerable<int?> list => list.Min(value => (int?)lambda.Evaluate(value)),
IEnumerable<long> list => list.Min(value => (long?)lambda.Evaluate(value)),
Expand All @@ -60,14 +70,15 @@ internal static void Evaluate(FunctionArgs functionArgs)
IEnumerable<decimal> list => list.Min(value => (decimal?)lambda.Evaluate(value)),
IEnumerable<decimal?> list => list.Min(value => (decimal?)lambda.Evaluate(value)),
IEnumerable<string?> list => list.Min(value => (string?)lambda.Evaluate(value)),
_ => throw new FormatException($"First {ExtensionFunction.Min} parameter must be an IEnumerable of a numeric type.")
IEnumerable<object?> list => GetMin(list.Select(value => lambda.Evaluate(value))),
_ => throw new FormatException($"First {ExtensionFunction.Min} parameter must be an IEnumerable of a string or numeric type when processing as a lambda.")
};

}

private static double GetMin(IEnumerable<object?> objectList)
{
double min = 0;
var min = double.PositiveInfinity;
foreach (var item in objectList)
{
var thisOne = item switch
Expand All @@ -83,10 +94,10 @@ private static double GetMin(IEnumerable<object?> objectList)
{
JTokenType.Float => jValue.Value<float>(),
JTokenType.Integer => jValue.Value<int>(),
_ => throw new FormatException($"Found unsupported JToken type '{jValue.Type}' when completing sum.")
_ => throw new FormatException($"Found unsupported JToken type '{jValue.Type}' when completing Min.")
},
null => 0,
_ => throw new FormatException($"Found unsupported type '{item?.GetType().Name}' when completing sum.")
_ => throw new FormatException($"Found unsupported type '{item?.GetType().Name}' when completing Min.")
};
if (thisOne < min)
{
Expand Down

0 comments on commit 2498767

Please sign in to comment.