diff --git a/maui/src/Charts/Axis/CategoryAxis.cs b/maui/src/Charts/Axis/CategoryAxis.cs index be23854c..b5292cc1 100644 --- a/maui/src/Charts/Axis/CategoryAxis.cs +++ b/maui/src/Charts/Axis/CategoryAxis.cs @@ -1,4 +1,4 @@ -using System.Collections; +using System.Collections; using System.Diagnostics.CodeAnalysis; namespace Syncfusion.Maui.Toolkit.Charts @@ -32,8 +32,8 @@ protected sealed override DoubleRange ApplyRangePadding(DoubleRange range, doubl internal void GroupData() { List groupingValues = []; - var groupingValuesSet = new HashSet(); List groupedDatas = []; + var groupingValuesSet = new HashSet(StringComparer.Ordinal); foreach (var item in RegisteredSeries) { @@ -43,7 +43,7 @@ internal void GroupData() { if (groupedDatas.Count != 0) { - for (int j = 0; j <= xValues.Count - 1; j++) + for (int j = 0; j < xValues.Count; j++) { if (groupingValuesSet.Add(xValues[j])) { @@ -60,9 +60,9 @@ internal void GroupData() } } } - else if (series.ActualXValues != null) + else if (series.ActualXValues is List doubleValues) { - foreach (var val in (series.ActualXValues as List)!) + foreach (var val in doubleValues) { var str = val.ToString(); groupingValues.Add(str); @@ -77,7 +77,7 @@ internal void GroupData() } var distinctXValues = groupingValues.Distinct().ToList(); - var indexMap = new Dictionary(distinctXValues.Count); + var indexMap = new Dictionary(distinctXValues.Count, StringComparer.Ordinal); for (int i = 0; i < distinctXValues.Count; i++) { indexMap[distinctXValues[i]] = i; @@ -89,11 +89,23 @@ internal void GroupData() if (series.ActualXValues is List list) { - series.GroupedXValuesIndexes = list.Select(val => (double)indexMap[val]).ToList(); + var indexes = new List(list.Count); + foreach (var val in list) + { + indexes.Add(indexMap.TryGetValue(val, out int idx) ? idx : -1); + } + + series.GroupedXValuesIndexes = indexes; } - else if (series.ActualXValues != null) + else if (series.ActualXValues is List doubleList) { - series.GroupedXValuesIndexes = (series.ActualXValues as List)!.Select(val => (double)indexMap[val.ToString()]).ToList(); + var indexes = new List(doubleList.Count); + foreach (var val in doubleList) + { + indexes.Add(indexMap.TryGetValue(val.ToString(), out int idx) ? idx : -1); + } + + series.GroupedXValuesIndexes = indexes; } series.GroupedXValues = distinctXValues; diff --git a/maui/tests/Syncfusion.Maui.Toolkit.UnitTest/Chart/Features/ChartFeatureAxisUnitTest.cs b/maui/tests/Syncfusion.Maui.Toolkit.UnitTest/Chart/Features/ChartFeatureAxisUnitTest.cs index a95537ed..4b3c1551 100644 --- a/maui/tests/Syncfusion.Maui.Toolkit.UnitTest/Chart/Features/ChartFeatureAxisUnitTest.cs +++ b/maui/tests/Syncfusion.Maui.Toolkit.UnitTest/Chart/Features/ChartFeatureAxisUnitTest.cs @@ -2505,5 +2505,157 @@ public void PointToValue_ShouldReturnCorrectValue_ForVerticalAxis() #endregion + #region GroupData Performance Tests + + [Fact] + public void GroupData_WithDuplicateValues_ProducesCorrectIndexes() + { + var axis = new CategoryAxis(); + var series1 = new LineSeries + { + ActualXValues = new List { "A", "B", "A", "C", "B" }, + ActualData = [1, 2, 3, 4, 5] + }; + + axis.RegisteredSeries = [series1]; + + axis.GroupData(); + + var expectedDistinctXValues = new List { "A", "B", "C" }; + var expectedIndexes = new List { 0, 1, 0, 2, 1 }; + + Assert.Equal(expectedDistinctXValues, series1.GroupedXValues); + Assert.Equal(expectedIndexes, series1.GroupedXValuesIndexes); + } + + [Fact] + public void GroupData_WithDoubleXValues_ProducesCorrectIndexes() + { + var axis = new CategoryAxis(); + var series1 = new LineSeries + { + ActualXValues = new List { 1.0, 2.0, 3.0 }, + ActualData = [10, 20, 30] + }; + + var series2 = new LineSeries + { + ActualXValues = new List { 2.0, 3.0, 4.0 }, + ActualData = [40, 50, 60] + }; + + axis.RegisteredSeries = [series1, series2]; + + axis.GroupData(); + + var expectedDistinctXValues = new List { "1", "2", "3", "4" }; + var expectedIndexesSeries1 = new List { 0, 1, 2 }; + var expectedIndexesSeries2 = new List { 1, 2, 3 }; + + Assert.Equal(expectedDistinctXValues, series1.GroupedXValues); + Assert.Equal(expectedIndexesSeries1, series1.GroupedXValuesIndexes); + Assert.Equal(expectedIndexesSeries2, series2.GroupedXValuesIndexes); + } + + [Fact] + public void GroupData_WithMultipleSeriesOverlappingValues_DeduplicatesCorrectly() + { + var axis = new CategoryAxis(); + var series1 = new LineSeries + { + ActualXValues = new List { "X", "Y", "Z" }, + ActualData = [1, 2, 3] + }; + + var series2 = new LineSeries + { + ActualXValues = new List { "X", "Y", "Z" }, + ActualData = [4, 5, 6] + }; + + axis.RegisteredSeries = [series1, series2]; + + axis.GroupData(); + + var expectedDistinctXValues = new List { "X", "Y", "Z" }; + var expectedIndexes = new List { 0, 1, 2 }; + + Assert.Equal(expectedDistinctXValues, series1.GroupedXValues); + Assert.Equal(expectedIndexes, series1.GroupedXValuesIndexes); + Assert.Equal(expectedIndexes, series2.GroupedXValuesIndexes); + } + + [Fact] + public void GroupData_WithSingleSeries_ProducesCorrectResults() + { + var axis = new CategoryAxis(); + var series1 = new LineSeries + { + ActualXValues = new List { "Mon", "Tue", "Wed", "Thu", "Fri" }, + ActualData = [10, 20, 30, 40, 50] + }; + + axis.RegisteredSeries = [series1]; + + axis.GroupData(); + + var expectedDistinctXValues = new List { "Mon", "Tue", "Wed", "Thu", "Fri" }; + var expectedIndexes = new List { 0, 1, 2, 3, 4 }; + + Assert.Equal(expectedDistinctXValues, series1.GroupedXValues); + Assert.Equal(expectedIndexes, series1.GroupedXValuesIndexes); + } + + [Fact] + public void GroupData_WithLargeDataset_CompletesWithCorrectResults() + { + var axis = new CategoryAxis(); + int dataSize = 1000; + var xValues1 = new List(dataSize); + var xValues2 = new List(dataSize); + var data1 = new List(dataSize); + var data2 = new List(dataSize); + + for (int i = 0; i < dataSize; i++) + { + xValues1.Add($"Item_{i}"); + data1.Add(i); + } + + for (int i = 500; i < dataSize + 500; i++) + { + xValues2.Add($"Item_{i}"); + data2.Add(i); + } + + var series1 = new LineSeries + { + ActualXValues = xValues1, + ActualData = data1 + }; + + var series2 = new LineSeries + { + ActualXValues = xValues2, + ActualData = data2 + }; + + axis.RegisteredSeries = [series1, series2]; + + axis.GroupData(); + + // Should have 1500 distinct values (0-999 from series1, 1000-1499 from series2) + Assert.Equal(1500, series1.GroupedXValues.Count); + + // First series indexes should be 0..999 + Assert.Equal(0.0, series1.GroupedXValuesIndexes[0]); + Assert.Equal(999.0, series1.GroupedXValuesIndexes[999]); + + // Second series: "Item_500" should map to index 500 + Assert.Equal(500.0, series2.GroupedXValuesIndexes[0]); + } + + #endregion + } }