A while ago I worked on this idea in a project where I needed to filter out ages of clients in a <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 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]]
I didn’t go through with it then. I might serve you as you are, things I remember I wanted to do:
- respect the order found in the result
- allow orders greater than 100 (the logic could be with
Math.floor(nr / 100)
and search for the N following words)
- filter the language first to avoid cases where words from other languages match.
If you want to use can see a live example here: https://jsfiddle.net/hdtqc12u/
Samir, I tested your solution (https://jsfiddle.net/hdtqc12u/1/) and noticed that it does not accept large letters in the numbers nor more than one occurrence per string. I don’t know if it’s important to AP. Otherwise ++
– Sergio
@Sergio, I think the problem is solved. Thank you for the addendum.
– Samir Braga
Personal thank you!!
– Thiago R.