UnitsNet icon indicating copy to clipboard operation
UnitsNet copied to clipboard

ToAutoUnitString

Open zdenek-cada opened this issue 1 year ago • 3 comments

I had created my owen Extension for ToAutoUnitString(...) ... it is very simple, the extension gets order of Value in different assumed units and the best one is used for conversion:

LengthUnit[] units = new LengthUnit[] { LengthUnit.Millimeter, LengthUnit.Meter, LengthUnit.Kilometer };
new Length(5.5e-3, LengthUnit.Meter).ToAutoUnitString(assumedUnits: units)
new Length(5.5,    LengthUnit.Meter).ToAutoUnitString(assumedUnits: units)
new Length(5.5e3,  LengthUnit.Meter).ToAutoUnitString(assumedUnits: units)

5.5e-3 m ---> 5.5 mm 5.5 m ---> 5.5 m 5.5e3 m ---> 5.5 km

Responsibility which units have to be used is on an user (array parameter: TQuantityUnit[] assumedUnits)

Extension:

public static LengthUnit[] BasicLengthUnits => new LengthUnit[] { LengthUnit.Millimeter, LengthUnit.Meter, LengthUnit.Kilometer };

public static string ToAutoUnitString<TQuantity, TQuantityUnit>(this TQuantity l, string valueFormat = "g", TQuantityUnit[] assumedUnits = null, IFormatProvider p = null)
    where TQuantity : IQuantity where TQuantityUnit : Enum
{ 
    TQuantityUnit best = assumedUnits.OrderBy(u => Math.Abs(Math.Log10(Math.Abs((double)l.ToUnit(u).Value))))
                                     .FirstOrDefault();
    return l.ToUnit(best).ToString(valueFormat, p);
}

is it useful?

zdenek-cada avatar Nov 08 '23 10:11 zdenek-cada

Sorry for late reply, yes this seems useful and something similar has been requested before. The example seems to work quite nicely. The only thing that I kind of miss, is some sane defaults out of the box, but I think it's fair to have the user provide this to ensure they get what they want.

Please go ahead with a pull request and add a few test cases for it with different quantities and units.

angularsen avatar Nov 27 '23 19:11 angularsen

One thing, it may be better to have the method return the unit, so that we can reuse the ToString() and all its overloads. Also throw if no units are provided.

Length.FromMillimeters(55.1234).ToAutoUnit(units2).ToString("s1"); // 5.5 cm
    public static TQuantity ToAutoUnit<TQuantity, TQuantityUnit>(this TQuantity quantity, TQuantityUnit[] units)
        where TQuantity : IQuantity where TQuantityUnit : Enum
    {
        if (quantity is null) throw new ArgumentNullException(nameof(quantity));
        if (units is null) throw new ArgumentNullException("Specify at least one unit, preferably multiple units.", nameof(units));

        TQuantityUnit best = units.OrderBy(u => Math.Abs(Math.Log10(Math.Abs((double)quantity.ToUnit(u).Value))))
                                         .FirstOrDefault();
        return (TQuantity)quantity.ToUnit(best);
    }

angularsen avatar Nov 27 '23 20:11 angularsen

Yes, agree, to have ToAutoUnit<...>(...) without 'String' it is obviously better! perfect ...

zdenek-cada avatar Nov 28 '23 07:11 zdenek-cada

This issue is stale because it has been open 30 days with no activity. Remove stale label or comment or this will be closed in 7 days.

github-actions[bot] avatar Jul 08 '24 17:07 github-actions[bot]

This issue was automatically closed due to inactivity.

github-actions[bot] avatar Jul 16 '24 02:07 github-actions[bot]