Some time ago I worked on this idea in a project where I needed to filter client ages in <input>
. Then I ended up changing the approach and creating buttons to receive numbers without having to filter them. But the idea was this:
var numbers = {
en: ['zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'ten', 'eleven', 'twelve', 'thirteen', 'fourteen', 'fifteen', 'sixteen', 'seventeen', 'eighteen', 'nineteen', 'twenty', 'thirty', 'forty', 'fifty', 'sixty', 'seventy', 'eighty', 'ninety', 'hundred'],
se: ['noll', 'ett', 'två', 'tre', 'fyra', 'fem', 'sex', 'sju', 'åtta', 'nio', 'tio', 'elva', 'tolv', 'tretton', 'fjorton', 'femton', 'sexton', 'sjutton', 'arton', 'nitton', 'tjugo', "trettio", "fyrtio", "femtio", "sextio", "sjuttio", "åttio", "nittio", "hundra"],
de: ["null", "eins", "zwei", "drei", "vier", "fünf", "sechs", "sieben", "acht", "neun", "zehn", "elf", "zwölf", "dreizehn", "vierzehn", "fünfzehn", "sechzehn", "siebzehn", "achtzehn", "neunzehn", "zwanzig", "dreißig", "vierzig", "fünfzig", "sechzig", "siebzig", "achtzig", "neunzig", "hundert"],
no: ["null", "en", "to", "tre", "fire", "fem", "seks", "sju", "åtte", "ni", "ti", "elleve", "tolv", "tretten", "fjorten", "femten", "seksten", "sytten", "atten", "nitten", "tyve", "tretti", "førti", "femti", "seksti", "sytti", "åtti", "nitti", "hundre"]
};
var mapper = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 30, 40, 50, 60, 70, 80, 90, 100];
function findNumber(string) {
var results = [];
Object.keys(numbers).forEach(function(lang) {
var nrs = numbers[lang];
nrs.forEach(function(nr, i) {
var rexep = new RegExp('[^\w\-]' + nr + '[^\w\-]|^' + nr + '[^\w\-]|[^\w\-]' + nr + '$|^' + nr + '$', 'gi');
var match = string.match(rexep);
if (match) {
var mappedNumber = mapper[i];
if (mappedNumber > 19) {
var customRegexp = new RegExp(match[0].trim() + '\s\w+', 'i');
var wholeNumber = string.match(customRegexp);
if (wholeNumber) mappedNumber = mappedNumber + results.pop();
}
results = results.concat(mappedNumber)
}
});
});
var more = string.match(/\d+/g) || [];
return results.concat(more).map(Number);
};
Basically this function compares text from different languages and extracts the numbers.
An example would be:
var testes = ['TWO WEEKS AGO', 'two weeks ago', 'I am thirty seven years old!', 'I was the the number five in my class! Now I am number one!'];
console.log(JSON.stringify(testes.map(findNumber))); // [[2],[2],[37],[1,5]]
At the time I did not go any further with this. It may be that it serves you as it is, things I remember wanting to do:
- Respect the order found in the result
- allow orders greater than 100 (logic could be with
Math.floor(nr / 100)
and search for the following N words)
- filter the language first to avoid cases where words from other languages match.
If you want to use it you can see a live example here: link