Skip to content

Commit 5c71a77

Browse files
authored
Add new functions in expression (#3470)
1 parent 6fabf93 commit 5c71a77

File tree

3 files changed

+92
-5
lines changed

3 files changed

+92
-5
lines changed

libraries/AdaptiveExpressions/ExpressionFunctions.cs

Lines changed: 85 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2437,15 +2437,27 @@ private static EvaluateExpressionDelegate SortBy(bool isDescending)
24372437
return (result, error);
24382438
};
24392439

2440+
// TODO we should uniform the list format
2441+
private static List<object> Object2List(JObject jobj)
2442+
{
2443+
var tempList = new List<object>();
2444+
foreach (var item in jobj)
2445+
{
2446+
tempList.Add(new { index = item.Key, value = item.Value });
2447+
}
2448+
2449+
return tempList;
2450+
}
2451+
24402452
private static (object, string) IndicesAndValues(Expression expression, object state)
24412453
{
24422454
object result = null;
24432455
string error;
2444-
object arr;
2445-
(arr, error) = expression.Children[0].TryEvaluate(state);
2456+
object instance;
2457+
(instance, error) = expression.Children[0].TryEvaluate(state);
24462458
if (error == null)
24472459
{
2448-
if (TryParseList(arr, out var list))
2460+
if (TryParseList(instance, out var list))
24492461
{
24502462
var tempList = new List<object>();
24512463
for (var i = 0; i < list.Count; i++)
@@ -2455,9 +2467,17 @@ private static (object, string) IndicesAndValues(Expression expression, object s
24552467

24562468
result = tempList;
24572469
}
2470+
else if (instance is JObject jobj)
2471+
{
2472+
result = Object2List(jobj);
2473+
}
2474+
else if (JToken.FromObject(instance) is JObject jobject)
2475+
{
2476+
result = Object2List(jobject);
2477+
}
24582478
else
24592479
{
2460-
error = $"{expression.Children[0]} is not array.";
2480+
error = $"{expression.Children[0]} is not array or object..";
24612481
}
24622482
}
24632483

@@ -2517,6 +2537,46 @@ private static int GetPropertyCount(dynamic obj)
25172537
return -1;
25182538
}
25192539

2540+
private static IEnumerable<object> Flatten(IEnumerable<object> list, int dept)
2541+
{
2542+
var result = list.ToList();
2543+
if (dept < 1)
2544+
{
2545+
dept = 1;
2546+
}
2547+
2548+
for (var i = 0; i < dept; i++)
2549+
{
2550+
var hasArray = result.Any(u => TryParseList(u, out var _));
2551+
if (hasArray)
2552+
{
2553+
var tempList = new List<object>();
2554+
foreach (var item in result)
2555+
{
2556+
if (TryParseList(item, out var itemList))
2557+
{
2558+
foreach (var childItem in itemList)
2559+
{
2560+
tempList.Add(childItem);
2561+
}
2562+
}
2563+
else
2564+
{
2565+
tempList.Add(item);
2566+
}
2567+
}
2568+
2569+
result = tempList.ToList();
2570+
}
2571+
else
2572+
{
2573+
break;
2574+
}
2575+
}
2576+
2577+
return result;
2578+
}
2579+
25202580
private static Dictionary<string, ExpressionEvaluator> GetExpressionFunctions()
25212581
{
25222582
var functions = new List<ExpressionEvaluator>
@@ -2784,6 +2844,27 @@ private static Dictionary<string, ExpressionEvaluator> GetExpressionFunctions()
27842844
ReturnType.Object,
27852845
(expression) => ExpressionFunctions.ValidateOrder(expression, new[] { ReturnType.String }, ReturnType.Object)),
27862846
new ExpressionEvaluator(ExpressionType.IndicesAndValues, IndicesAndValues, ReturnType.Object, ValidateUnary),
2847+
new ExpressionEvaluator(
2848+
ExpressionType.Flatten,
2849+
Apply(
2850+
args =>
2851+
{
2852+
IEnumerable<object> result = args[0];
2853+
var depth = args.Count > 1 ? args[1] : 100;
2854+
return ExpressionFunctions.Flatten(result, depth);
2855+
}),
2856+
ReturnType.Object,
2857+
(expression) => ValidateOrder(expression, new[] { ReturnType.Number }, ReturnType.Object)),
2858+
new ExpressionEvaluator(
2859+
ExpressionType.Unique,
2860+
Apply(
2861+
args =>
2862+
{
2863+
IEnumerable<object> result = args[0];
2864+
return result.Distinct().ToList();
2865+
}, VerifyList),
2866+
ReturnType.Object,
2867+
(expression) => ValidateOrder(expression, null, ReturnType.Object)),
27872868

27882869
// Booleans
27892870
Comparison(ExpressionType.LessThan, args => args[0] < args[1], ValidateBinaryNumberOrString, VerifyNumberOrString),

libraries/AdaptiveExpressions/ExpressionType.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ public static class ExpressionType
7171
public const string SortBy = "sortBy";
7272
public const string SortByDescending = "sortByDescending";
7373
public const string IndicesAndValues = "indicesAndValues";
74+
public const string Flatten = "flatten";
75+
public const string Unique = "unique";
7476

7577
// DateTime
7678
public const string AddDays = "addDays";

tests/AdaptiveExpressions.Tests/ExpressionEngineTests.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -691,6 +691,7 @@ public class ExpressionEngineTests
691691
Test("join(where(items, item, item == 'two'), ',')", "two"),
692692
Test("string(where(dialog, item, item.value=='Dialog Title'))", "{\"title\":\"Dialog Title\"}"),
693693
Test("first(where(indicesAndValues(items), elt, elt.index > 1)).value", "two"),
694+
Test("first(where(indicesAndValues(bag), elt, elt.index == \"three\")).value", 3),
694695
Test("join(foreach(where(nestedItems, item, item.x > 1), result, result.x), ',')", "2,3", new HashSet<string> { "nestedItems" }),
695696
Test("join(foreach(doubleNestedItems, items, join(foreach(items, item, concat(y, string(item.x))), ',')), ',')", "y1,y2,y3"),
696697
Test("join(foreach(doubleNestedItems, items, join(foreach(items, item, items[0].x), ',')), ',')", "1,1,3"),
@@ -729,6 +730,9 @@ public class ExpressionEngineTests
729730
Test("sortBy(nestedItems, 'x')[0].x", 1),
730731
Test("sortByDescending(items)", new List<object> { "zero", "two", "one" }),
731732
Test("sortByDescending(nestedItems, 'x')[0].x", 3),
733+
Test("flatten(createArray(1,createArray(2),createArray(createArray(3, 4), createArray(5,6))))", new List<object> { 1, 2, 3, 4, 5, 6 }),
734+
Test("flatten(createArray(1,createArray(2),createArray(createArray(3, 4), createArray(5,6))), 1)", new List<object> { 1, 2, new List<object>() { 3, 4 }, new List<object>() { 5, 6 } }),
735+
Test("unique(createArray(1, 5, 1))", new List<object>() { 1, 5 }),
732736
#endregion
733737

734738
#region Object manipulation and construction functions
@@ -921,7 +925,7 @@ private void AssertObjectEquals(object expected, object actual)
921925
Assert.AreEqual(expectedList.Count, actualList.Count);
922926
for (var i = 0; i < expectedList.Count; i++)
923927
{
924-
Assert.AreEqual(ResolveValue(expectedList[i]), ResolveValue(actualList[i]));
928+
AssertObjectEquals(ResolveValue(expectedList[i]), ResolveValue(actualList[i]));
925929
}
926930
}
927931
else

0 commit comments

Comments
 (0)