Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ToAutoUnitString #1327

Open
zdenek-cada opened this issue Nov 8, 2023 · 3 comments
Open

ToAutoUnitString #1327

zdenek-cada opened this issue Nov 8, 2023 · 3 comments

Comments

@zdenek-cada
Copy link

zdenek-cada commented Nov 8, 2023

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?

@angularsen
Copy link
Owner

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
Copy link
Owner

angularsen commented Nov 27, 2023

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);
    }

@zdenek-cada
Copy link
Author

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants