Javascript 如何检测某人在输入字段中键入的单位

Javascript 如何检测某人在输入字段中键入的单位,javascript,reactjs,Javascript,Reactjs,我希望能够检测到有人在自由文本输入字段中键入的单位。例如,如果他们输入100kg,我想检测它的重量。如果输入100升,则应检测体积,依此类推。我希望它能用于不同风格的输入。例如,100kg和100kg都应检测为重量 这就是我目前构建它的方式。它适用于简单的示例,但存在一些问题: import React from 'react'; import { render } from 'react-dom'; import PropTypes from 'prop-types'; import { ob

我希望能够检测到有人在自由文本输入字段中键入的单位。例如,如果他们输入
100kg
,我想检测它的
重量。如果输入
100升
,则应检测
体积
,依此类推。我希望它能用于不同风格的输入。例如,
100kg
100kg
都应检测为重量

这就是我目前构建它的方式。它适用于简单的示例,但存在一些问题:

import React from 'react';
import { render } from 'react-dom';
import PropTypes from 'prop-types';
import { observer } from "mobx-react";


@observer
export default class DemoComponent extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            inputValue: "",
            unit: "no unit detected",
        }
    }

    updateInputValue(e) {
        let unit = this.detectUnit(e.target.value);
        if(unit) {
            this.setState({unit: unit,inputValue: e.target.value});
        } else {
            this.setState({unit: "no unit detected",inputValue: 
            e.target.value})
        }
    }

    detectUnit(string) {
        let currentUnit = false;
        let cleanedString = string.toLowerCase();
        for (let unit in units) {
            if (units.hasOwnProperty(unit)) {
                // do stuff
                for(let i = 0; i < units[unit].length ; i++) {
                    if(cleanedString.includes(units[unit][i])) {
                        currentUnit = unit;
                        break;
                    }
                }
            }
        }
        console.log(currentUnit)
        return currentUnit;        
    }
    render() {
        return (
            <div id="testID">
                <h1 className="democss">{this.props.title}</h1>
            <div className="container">
                <input value={this.state.inputValue} onChange={(e) => 
                this.updateInputValue(e)} />
                <h2 className="unit">{this.state.unit}</h2>
            </div>
            </div>
        );
    }
}

const units = {
    velocity: ["m/s","km/h","meter/s","m/sekund", "meter/sekund",],
    weight: ["kg","kilogram","kilo gram","kgram","k gram","kilo","k"],
    volume: ["liter",], //add "l" later
}
从“React”导入React;
从'react dom'导入{render};
从“道具类型”导入道具类型;
从“mobx react”导入{observer};
@观察者
导出默认类DemoComponent扩展React.Component{
建造师(道具){
超级(道具);
此.state={
输入值:“”,
单位:“未检测到单位”,
}
}
更新输入值(e){
设单位=this.detectUnit(即目标值);
若有(单位){
this.setState({unit:unit,inputValue:e.target.value});
}否则{
this.setState({unit:“未检测到单元”),inputValue:
e、 target.value})
}
}
检测器(字符串){
设currentUnit=false;
让cleanedString=string.toLowerCase();
for(以单位表示){
if(单位hasOwnProperty(单位)){
//做事
对于(设i=0;i
{this.state.unit}
);
}
}
常数单位={
速度:[“米/秒”、“公里/小时”、“米/秒”、“米/秒”、“米/秒”、“米/秒”,
重量:[“千克”、“千克”、“千克”、“千克”、“千克”、“千克”、“克”、“克”、“千克”、“克”],
体积:[“升”,“升],//稍后添加“l”
}
如果我输入
randomlile
,它会将其检测为音量,因为字符串
little
存在。我如何修复它,使它只检查精确匹配,同时仍然能够接受多种输入样式,如

100公斤
100公斤
100公斤

并将它们全部检测为重量? 这是我可以用正则表达式的东西吗?关键是他们可以自由输入值和单位,我需要检测值和单位

编辑:Mad的答案更好。如果您只是简单地将“随机升”与“升”进行比较,我下面的答案会更好,但您将“100随机升”与“升”进行比较,这使得Mad使用正则表达式的方法更适用。我将把下面的答案留给子孙后代

不要检查
单元
数组中的每个项目是否存在于
清洁字符串
中,而是用另一种方法检查
清洁字符串
是否存在于
单元
数组中:

也就是说,与此相反:

for (let unit in units) {
    if (units.hasOwnProperty(unit)) {
        // do stuff
        for(let i = 0; i < units[unit].length ; i++) {
            if(cleanedString.includes(units[unit][i])) {
                currentUnit = unit;
                break;
            }
        }
    }
}
说明:

  • units[unit]
    是字符串数组
  • units[unit][i]
    是一个字符串
  • cleanedString
    是一个字符串
{stringA}.includes({stringB})
检查
stringB
是否是
stringA

cleanedString.includes(units[unit][i]))
// ...is the same as
'randomliter'.includes('liter')
// ...which will return 'true'
{array}.includes({stringB})
检查
stringB
是否与
数组中的一个值完全匹配

units[unit].includes(cleanedString)
// ...is the same as
['liter'].includes('randomliter')
// ...which will return 'false'.

对正则表达式使用
match
,而不是
includes

以下内容应该与您想要的kg示例相关

regex = '^[0-9]*\s*kg\s*[0-9]*$'
cleanedString.match(regex)
有关正则表达式的演示/解释,请参阅。

尝试以下方法:

function detectUnit(string) {
  const unit = string.replace(/\d+/g,'').trim().toLowerCase();
  switch(true) {
    case units.velocity.includes(unit):
        return "velocity";
    case units.weight.includes(unit):
        return "weight";
    case units.volume.includes(unit):
        return "volume";
    default:
        return "default";
  }
}

以下函数将返回确切的类型:

const units = {
    velocity: ["m/s", "km/h", "meter/s", "m/sekund", "meter/sekund",],
    weight: ["kg", "kilogram", "kilo gram", "kgram", "k gram", "kilo", "k"],
    volume: ["liter", "l"]
}

Object.entries(units).find(([name, typos]) => typos.some(typo => inputValue.includes(typo)))
此函数迭代数组中的每个单元类型,然后遍历每个不同的字符串,如果其中一个匹配,则返回整个对象

工作示例:

函数getUnit(inputValue){ 常数单位={ 速度:[“米/秒”、“公里/小时”、“米/秒”、“米/秒”、“米/秒”、“米/秒”, 重量:[“千克”、“千克”、“千克”、“千克”、“千克”、“千克”、“克”、“克”、“千克”、“克”], 体积:[“升”,“升”] } const result=Object.entries(units.find)([name,typos])=>typos.some(typo=>inputValue.includes(typo))) 返回结果?结果[0]:空 } 控制台日志(getUnit('450 kg')) console.log(getUnit('4l')) 控制台日志(getUnit('50米/秒')) console.log(getUnit('850 rfeh')) 日志(getUnit('4.56 kgram')) 控制台日志(getUnit('756升'))
log(getUnit('758米/sekund'))
您正在使用的
includes()
。您可能应该精确匹配字符串。或者做一个单词匹配。如果您正在使用
for..in
,则不需要
if(units.hasOwnProperty(unit))
。您可以假设
单元
在迭代中确实显示了每个属性。这不是很枯燥。您应该使用某种迭代,而不是为每种单元类型硬编码一个案例。
const units = {
    velocity: ["m/s", "km/h", "meter/s", "m/sekund", "meter/sekund",],
    weight: ["kg", "kilogram", "kilo gram", "kgram", "k gram", "kilo", "k"],
    volume: ["liter", "l"]
}

Object.entries(units).find(([name, typos]) => typos.some(typo => inputValue.includes(typo)))