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

时间:2019-01-29 15:49:38

标签: javascript reactjs

我希望能够检测到有人在自由文本输入字段中键入的单位。例如,如果他们键入100 kg,我想检测出它是weight。如果他们输入100 liter,它将检测到volume,依此类推。我希望它适用于不同风格的输入。例如,100kg100 kg应该都被检测为体重。

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

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
}

如果我输入randomliter,它将因为字符串liter而将其检测为音量。我该如何解决,以便它只检查完全匹配,同时仍然能够接受多种输入样式,例如

100kg 100 kg kg 100

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

4 个答案:

答案 0 :(得分:3)

使用match而不是includes的正则表达式。

以下应针对kg示例执行以下操作。

regex = '^[0-9]*\s*kg\s*[0-9]*$'
cleanedString.match(regex)

有关正则表达式的演示/说明,请参见here

答案 1 :(得分:2)

  

编辑:Mad的答案更好。如果您只是将“ randomLiter”与“ liter”进行比较,那么我的回答会更好,但您将“ 100 randomLiters”与“ liter”进行了比较,使Mad使用RegEx的方法更加适用。为了后代,我将在下面留下答案。

不是检查unit数组中是否存在每个项目,而是反过来检查cleanedString数组中是否存在cleanedString

也就是说,代替这个:

unit

...执行此操作:

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

说明:

  • for (let unit in units) { if(units[unit].includes(cleanedString)){ 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中的值之一完全匹配

array

答案 2 :(得分:0)

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

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

此函数遍历数组中的每个单元类型,然后遍历每个不同的字符串(如果匹配),它将返回整个对象。

工作示例:

function getUnit(inputValue){
  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"]
  }

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

  return result ? result[0] : null
}

console.log(getUnit('450 kg'))
console.log(getUnit('4 l'))
console.log(getUnit('50 meter/s'))
console.log(getUnit('850 rfeh'))
console.log(getUnit('4.56 kgram'))
console.log(getUnit('756 liter'))
console.log(getUnit('758 meter/sekund'))

答案 3 :(得分:-1)

尝试一下:

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