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

Read available units/unit data structure #14

Open
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

mikberg
Copy link
Contributor

@mikberg mikberg commented Jun 14, 2014

I'm looking for a way to extract (the names of) all the units available in the library, e.g. "m", "meter", "meters", "metre", "metres", "in, "inch", "inches". Is it possible to access the internal object holding these names today?

I am parsing quantities from a text input field, and want to have a typeahead feature. The way I currently do this is by a manually extracted array, which leads to errors or more labour when this library is updated.

@rage-shadowman
Copy link
Contributor

No, there is nothing in the current trunk to do this. But you could easily add a method to parse the UNITS variable. Maybe getPrefixes, getKinds and getUnits(kind) functions? They should be fairly easy to write.

@gentooboontoo
Copy link
Owner

@mikberg the easy solution would be to expose the internal unit definition object for maximum usage flexibility but it would be a bad idea to let client code to mess with internal structures. So I prefer a cleaner API to retrieve these unit names.
I am OK with functions proposed by @rage-shadowman. They are clear, rather simple to implement and should meet your needs as far as I understand:

getPrefixes() -> ["googol","Ki","Kibi","kibi","Mi","Mebi","mebi",...]
getKinds() -> ["resistance","inductance",...]
// optional kind parameter to filter on a specific kind, all units otherwise
getUnits("radiation") -> ["Gy","gray","grays","R","roentgen",...]

Feel free to make a PR based on this. Otherwise I will add such a feature when a little bit less busy.

@mikberg
Copy link
Contributor Author

mikberg commented Jun 10, 2014

This looks simple and nice, perfect for my needs. I might take a swing at implementing something sometime this week.

My only concern with this API is that the different names for the same units are not grouped. Perfect for my needs, but it might not suit all.

What about something like this?

getPrefixes() -> [["googol"], ["Ki", "Kibi", "kibi"], ["Mi", "Mebi", "mebi"], ...]
getKinds() -> ["resistance", "inductance", ...]
// optional kind parameter to filter on a specific kind, all units otherwise
getUnits("radiation") -> [["Gy","gray","grays"],["R","roentgen"], ...]

@gentooboontoo
Copy link
Owner

It's OK to group names since it keeps some useful information. If needed, it will be up to client code to flatten/sort or anything else with returned lists.

@rage-shadowman
Copy link
Contributor

Another alternative, if you don't want ambiguous arrays, would be to return only the unit names (ie: for "" return "liter" -- the name sans the "<>" chars) and a getAliases method to get all the aliases for a named unit (["l", "L", "liter", "liters", "litre", "litres"]) or maybe event all the alternative aliases for a given alias (such that getAlternatives("liter") returns an identical array to getAlternatives("L")).

The long names always appear to be one of the aliases, but they are not always the first alias in the list. Although getting alternatives for prefixes and for units may require separate methods (otherwise what should getAlternatives("m") return?).

@mikberg
Copy link
Contributor Author

mikberg commented Jun 14, 2014

I went through several designs, but ended up with simply a getUnits() function returning a nested object with kinds as keys. The values are objects with unit names as keys and arrays of synonyms as values.

{
  length: {
    m: ["m", "meter", "meters", "metre", "metres",
    ...
  },
  "area": { ... },
  ...

Prefixes are also included. The return value can be restricted to only one kind by an optional "kind" argument, Qty.getUnits("prefix") or Qty.getUnits("resistance").

I'm of course open to modifying.

@rage-shadowman
Copy link
Contributor

@mikberg would the unit name "meter" (as opposed to "m") be more useful as the key for a unit?

@mikberg
Copy link
Contributor Author

mikberg commented Jun 16, 2014

Yes, of course. I'm sorry, that was a typo. The real output, this time copy-pasted, is:

...,
length:
   { meter: [ 'm', 'meter', 'meters', 'metre', 'metres' ],
     inch: [ 'in', 'inch', 'inches', '"' ],
     foot: [ 'ft', 'foot', 'feet', '\'' ],
     yard: [ 'yd', 'yard', 'yards' ],
     mile: [ 'mi', 'mile', 'miles' ],
     'naut-mile': [ 'nmi' ],
     league: [ 'league', 'leagues' ],
     furlong: [ 'furlong', 'furlongs' ],
     rod: [ 'rd', 'rod', 'rods' ],
     mil: [ 'mil', 'mils' ],
     angstrom: [ 'ang', 'angstrom', 'angstroms' ],
     fathom: [ 'fathom', 'fathoms' ],
     pica: [ 'pica', 'picas' ],
     point: [ 'pt', 'point', 'points' ],
     redshift: [ 'z', 'red-shift' ],
     AU: [ 'AU', 'astronomical-unit' ],
     'light-second': [ 'ls', 'light-second' ],
     'light-minute': [ 'lmin', 'light-minute' ],
     'light-year': [ 'ly', 'light-year' ],
     parsec: [ 'pc', 'parsec', 'parsecs' ] },
  mass:
   { kilogram: [ 'kg', 'kilogram', 'kilograms' ],
     AMU: [ 'u', 'AMU', 'amu' ],
     dalton: [ 'Da', 'Dalton', 'Daltons', 'dalton', 'daltons' ]
     ...

@gentooboontoo
Copy link
Owner

Thank you @mikberg for the PR. Two remarks however:

I prefer you keep your previous getPrefixes() and getKinds() methods. It would be cleaner and more logical than getUnits("prefix") (getUnits() should not reflect the internal unit definition structure that could change in the future) and getKinds could be simply implemented by returning the list of values from KINDS inner variable. Of course, getUnits("prefix") should have the same behavior than calling getUnits() with an unknown kind.

If possible (but not necessarily part of this PR), it could also be interesting to have a getAliases() / getAlternatives() method as proposed by @rage-shadowman. It would return the same array when called with any alias from a specific unit:

getAliases('m'); -> [ 'm', 'meter', 'meters', 'metre', 'metres' ]
getAliases('metres'); -> [ 'm', 'meter', 'meters', 'metre', 'metres' ]

@vsmalladi
Copy link
Contributor

I was thinking about aliases that @gentooboontoo was discussing earlier. The main issue is there are single letter aliases that exist between many different unit types, so there is no way of knowing which unique list you would want back.

One way is to set it up to provide the alias value and the unit type. Thoughts?

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

Successfully merging this pull request may close these issues.

None yet

4 participants