【问题标题】:Cooking unit measure conversion library烹饪单位度量转换库
【发布时间】:2021-01-22 06:38:52
【问题描述】:

我正在 React 中构建鸡尾酒配方应用程序,用户应该能够查看各种测量中的剂量单位。

默认情况下,我在“ml”中显示所有值,用户也可以选择在“cl”、“oz”或“part”中查看它。根据用户选择的内容,我需要根据选择的单位度量转换数量值。

我当前的代码:


dosageData = [
  {
    "dosageIngredient": "gin",
    "quantity": "30",
    "unit": "ml",
  },
  {
    "dosageIngredient": "campari",
    "quantity": "30",
    "unit": "ml",
  },
  {
    "dosageIngredient": "sweet red vermouth",
    "quantity": "30",
    "unit": "ml",
  },
]

当用户更改单位度量时 unitHandler() 被调用传递选择为“cl”、“ml”、“oz”、“part”的选项

const unitHandler = (option) => {    
    const newDosage = dosageData;
    switch (option) {
      case "cl":
        newDosage.map((item) => {
          item.unit = option; //changing the unit value of each item in the array to "cl"     
          var amount = parseInt(item.quantity);     
          // amount = [conversion formula]
          setDosageData(newDosage); 
          setToggleUnit(option);
        });
        break;
      case "ml":
        newDosage.map((item) => {
          item.unit = option;
          setDosageData(newDosage);
          setToggleUnit(option);
        });        
        break;
      case "oz":
        ...
        break;
      case "part":
        ...
        break;
      default:
        Alert.alert("Value not found");
    }    
  };

如果我们使用“cl”选项作为示例,我已经设法更改了数组中的单位类型并保存了新数组。 我错过了在数组中转换实际值“数量”的步骤。

如果需要,我有公式的参数 From (toggleUnit) 和 To ("option")。

我尝试使用以下库https://www.npmjs.com/package/mathjs,但它只能在“ml”和“cl”之间工作。

是否有更完整的库或现有的 JS 函数可用。

【问题讨论】:

    标签: javascript arrays reactjs react-native data-conversion


    【解决方案1】:

    对于度量单位之间的转换,在过去的项目中,我编写了以下类,它定义了一个包含浮点值属性和相关单位的对象。例如,“5 盎司”或“2 加仑”。该类由...实例化...

    • let v0 = new ValueUnits( '1 gal' ); // 值和单位至少用一个空格隔开。
    • let v1 = new ValueUnits( 1, 'gal' );

    该类还实现了一个toUnits( units ) 方法,该方法将对象值转换为传递的units。比如……

    • v0.toUnits( 'qt' );

    ...将v0 值属性转换为美制夸脱。请注意,toUnits( units ) 方法四舍五入到 10 位的精度,因此定义转换等效项的 ValueUnits.unitsMap 表也必须包含 10 位或更多位有效数字。否则如果对同一个ValueUnits对象执行多个单位转换,就会开始引入小错误。

    下面的代码示例定义ValueUnits类,然后实例化'1 gal',转换gal -> oz -> ml -> l -> qt -> gal...

    class ValueUnits {
      constructor( value, units ) {
        
        let fValue, fUnits;
    
            if ( units ) {
                fValue = value;
                fUnits = units;
            } else {
          [ fValue, fUnits ] = value.replace(/\s+/g, ' ').trim().split( ' ' );
          fValue = parseFloat( fValue );
            }
        
        fUnits = fUnits || '';
        
            if ( ValueUnits.unitsMap[ fUnits ] ) {
                this.value = fValue;
                this.units = fUnits;
            } else {
                this.value = fValue;
                this.units = '';
            }
        
      }
      
      toUnits( units ) {
    
            if ( ValueUnits.unitsMap[ this.units ].dimension !== ValueUnits.unitsMap[ units ].dimension ) {
                this.value = NaN;
                this.units = null;
            } else {
                this.value = parseFloat( ( this.value * ValueUnits.unitsMap[ this.units ].conversion / ValueUnits.unitsMap[ units ].conversion ).toPrecision( 10 ) );
                this.units = units;
            }
            return this;
        
        }
        
        unitsDimension() {
    
            return ValueUnits.unitsMap[ this.units ].dimension;
            
        }
      
    }
    
    ValueUnits.unitsMap = {
      '':    { dimension: 'number', conversion: 1},
      '%':   { dimension: 'number', conversion: 1 / 100},
    
      'pts': { dimension: 'length', conversion: 1 },
      'px':  { dimension: 'length', conversion: 72 / 128 },
      'in':  { dimension: 'length', conversion: 72 },
      '"':   { dimension: 'length', conversion: 72 },
      'ft':  { dimension: 'length', conversion: 72 * 12 },
      "'":   { dimension: 'length', conversion: 72 * 12 },
      'cm':  { dimension: 'length', conversion: 72 / 2.54 },
      'mm':  { dimension: 'length', conversion: 72 / 25.4 },
      
      '/pts':{ dimension: '/length', conversion: 1 / 1 },
      '/in': { dimension: '/length', conversion: 1 / 72 },
      '/px': { dimension: '/length', conversion: 128 / 72 },
    
      'l':   { dimension: 'volume', conversion: 1 },      // liters is base
      'dl':  { dimension: 'volume', conversion: 1 / 10 },
      'cl':  { dimension: 'volume', conversion: 1 / 100 },            
      'ml':  { dimension: 'volume', conversion: 1 / 1000 },
      'oz':  { dimension: 'volume', conversion: 1 / 33.814022702 },  // us fluid ounce
      'gal': { dimension: 'volume', conversion: 1 / 0.2641720524 },  // us gallon
      'qt':  { dimension: 'volume', conversion: 1 / 1.0566882094 },  // us quart
      'pt':  { dimension: 'volume', conversion: 1 / 2.1133764189 }   // us pint
    };
    
    
    let x = new ValueUnits( '1 gal' );
    console.log( x );
    
    x.toUnits( 'oz' );
    console.log( x );
    
    x.toUnits( 'ml' );
    console.log( x );
    
    x.toUnits( 'l' );
    console.log( x );
    
    x.toUnits( 'qt' );
    console.log( x );
    
    x.toUnits( 'gal' );
    console.log( x );

    我意识到这个类可能不完全适合您的代码当前的构造方式,但它抽象了数量的处理而不考虑单位,并简化了到所需单位的转换。

    请注意,“份”不是一个单位,而是物质之间的相对量度。也就是说,不能肯定地说partgal,但可以肯定地说1 qt0.25 gal...

    另外,体积等值来自https://www.unitconverters.net/volume/liters-to-gallons.htm

    【讨论】:

    • 感谢@jon-trent 的回答。由于我只有几个选项,因此我找到了它们之间的转换率并将其应用到 Switch Case 语句中。我猜不是很优雅但很实用。我还想出了如何解决零件转换问题。再次感谢!
    猜你喜欢
    • 2011-07-03
    • 2010-11-04
    • 2011-09-24
    • 2011-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-24
    • 1970-01-01
    相关资源
    最近更新 更多