public string Format(ModalityData data, string numberFormat = null, IFormatProvider numberFormatProvider = null)
        {
            int modality  = data.Modality;
            var formatter = new ManualModalityDataFormatter
            {
                PresentCount         = modality <= 2,
                PresentModeLocations = modality <= 1,
                PresentOutliers      = true,
                CompactMiddleModes   = true
            };

            return(formatter.Format(data, numberFormat, numberFormatProvider));
        }
示例#2
0
        public string Format(ModalityData data, string numberFormat = null, IFormatProvider numberFormatProvider = null)
        {
            Assertion.NotNull(nameof(data), data);

            var outlierDetectorFactory = OutlierDetectorFactory ?? SimpleOutlierDetectorFactory.DoubleMad;

            numberFormat ??= "N2";
            numberFormatProvider ??= DefaultCultureInfo.Instance;

            bool compactMode = CompactMiddleModes && data.Modality > 2;
            var  modes       = compactMode
                ? new[] { data.Modes.First(), data.Modes.Last() }
                : data.Modes;
            var  builder = new StringBuilder();
            var  bunch   = new Bunch();
            bool isFirst = true;

            void AddBunch(char open, string multiSeparator, char close)
            {
                if (bunch.Any())
                {
                    if (isFirst)
                    {
                        isFirst = false;
                    }
                    else
                    {
                        builder.Append(GroupSeparator);
                    }
                    bunch.Present(builder, open, multiSeparator, close, PresentCount, numberFormat, numberFormatProvider);
                }
            }

            void AddMode() => AddBunch('[', "; ", ']');
            void AddOutliers() => AddBunch('{', "..", '}');

            void AddMiddleNodesIfNeeded(int index)
            {
                if (index == 0 && compactMode)
                {
                    int extraModes = data.Modality - 2;
                    if (isFirst)
                    {
                        isFirst = false;
                    }
                    else
                    {
                        builder.Append(GroupSeparator);
                    }
                    builder.Append('<');
                    builder.Append(extraModes);
                    builder.Append(' ');
                    builder.Append(extraModes > 1 ? "modes" : "mode");
                    builder.Append('>');
                }
            }

            if (PresentOutliers)
            {
                for (int i = 0; i < modes.Count; i++)
                {
                    var mode            = modes[i];
                    var outlierDetector = outlierDetectorFactory.Create(mode.Values);
                    int index           = 0;

                    // *Lower outliers*
                    while (index < mode.Values.Count && outlierDetector.IsLowerOutlier(mode.Values[index]))
                    {
                        bunch.Add(mode.Values[index++]);
                    }
                    if (!(compactMode && i != 0))
                    {
                        AddOutliers();
                    }
                    bunch.Clear();

                    // *Central values*
                    while (index < mode.Values.Count && !outlierDetector.IsOutlier(mode.Values[index]))
                    {
                        bunch.Add(mode.Values[index++]);
                    }
                    if (PresentModeLocations)
                    {
                        bunch.Mode = mode.Location;
                    }
                    AddMode();
                    bunch.Clear();

                    // *Upper outliers*
                    while (index < mode.Values.Count && outlierDetector.IsUpperOutlier(mode.Values[index]))
                    {
                        bunch.Add(mode.Values[index++]);
                    }
                    // Propagate bunch to the lower outliers of the next mode

                    AddMiddleNodesIfNeeded(i);
                }

                AddOutliers(); // Upper outliers of the last mode
            }
            else
            {
                for (int i = 0; i < modes.Count; i++)
                {
                    var mode = modes[i];
                    bunch.Min = mode.Min();
                    bunch.Max = mode.Max();
                    if (PresentModeLocations)
                    {
                        bunch.Mode = mode.Location;
                    }
                    bunch.Count = mode.Values.Count;
                    AddBunch('[', "; ", ']');
                    AddMiddleNodesIfNeeded(i);
                }
            }

            return(builder.ToString());
        }