Is there a better way to extract information from a string?
One approach could be using map() over the elements of the array applying the match on each element, and finally call flat() to get the desired result:
let infoArr = [
"1 Ben Howard 12/16/1988 apple",
"2 James Smith 1/10/1999 orange",
"3 Andy Bloss 10/25/1956 apple",
"4 Carrie Walters 8/20/1975 peach",
"5 Doug Jones 11/10/1975 peach"
];
const result = infoArr.map(o => o.match(/(\d{1,2}\/){2}\d{4}/g)).flat();
console.log(result);
Alternatively, you could use flatMap():
let infoArr = [
"1 Ben Howard 12/16/1988 apple",
"2 James Smith 1/10/1999 orange",
"3 Andy Bloss 10/25/1956 apple",
"4 Carrie Walters 8/20/1975 peach",
"5 Doug Jones 11/10/1975 peach"
];
const result = infoArr.flatMap(o => o.match(/(\d{1,2}\/){2}\d{4}/g));
console.log(result);
Also, if you need to remove null
values from the final array in the case there are strings without dates, you can apply filter()
, like this:
const result = infoArr.map(o => o.match(/(\d{1,2}\/){2}\d{4}/g))
.flat()
.filter(date => date !== null);
const result = infoArr.flatMap(o => o.match(/(\d{1,2}\/){2}\d{4}/g))
.filter(date => date !== null);
An example with conflicting data:
let infoArr = [
"1 Ben Howard 12/16/1988 apple 10/22/1922",
"2 James Smith orange",
"3 Andy Bloss 10/25/1956 apple",
"4 Carrie Walters 8/20/19075 peach",
"5 Doug Jones 11/10-1975 peach"
];
const result = infoArr.flatMap(o => o.match(/(\d{1,2}\/){2}\d{4}/g))
.filter(date => date !== null); /* or filter(date => date) */
console.log(result);
Alternative without flat():
Since flat()
and flatMap()
are still currently "experimental", subject to change, and some browser (or versions) don't support it, you can use next alternative with the limitation that will only get the first match on every string
:
const infoArr = [
"1 Ben Howard 12/16/1988 apple 10/22/1922",
"2 James Smith orange",
"3 Andy Bloss 10/25/1956 apple",
"4 Carrie Walters 8/20/19075 peach",
"5 Doug Jones 11/10-1975 peach"
];
const getData = (input, regexp, filterNulls) =>
{
let res = input.map(o =>
{
let matchs = o.match(regexp);
return matchs && matchs[0];
});
return filterNulls ? res.filter(Boolean) : res;
}
console.log(getData(infoArr, /(\d{1,2}\/){2}\d{4}/g, false));
console.log(getData(infoArr, /(\d{1,2}\/){2}\d{4}/g, true));
Although this works, it is clunky and requires
pop()
because it will return an array of arrays, ie:["12/16/1988", "16/"]
, plus I need to callflat
afterwards.
The regex exec
method always has its match in the 0
property (assuming that it matches at all), you can just access that and push it to your array:
let infoArr = [
"1 Ben Howard 12/16/1988 apple",
"2 James Smith 1/10/1999 orange",
"3 Andy Bloss 10/25/1956 apple",
"4 Carrie Walters 8/20/1975 peach",
"5 Doug Jones 11/10/1975 peach"
];
function extractDates(arr){
const dateRegex = /(\d{1,2}\/){2}\d{4}/g;
const dateArr = [];
for (const str of arr){
const date = /(\d{1,2}\/){2}\d{4}/g.exec(str);
dateArr.push(date[0]);
}
return dateArr;
}
console.log(extractDates(infoArr));
(of course you could also do the same in a map
callback)
One option would be to join the strings by a separator that won't be matched, like ,
, then just perform the global match to get an array of dates from it:
let infoArr = [
"1 Ben Howard 12/16/1988 apple",
"2 James Smith 1/10/1999 orange",
"3 Andy Bloss 10/25/1956 apple",
"4 Carrie Walters 8/20/1975 peach",
"5 Doug Jones 11/10/1975 peach"
];
const result = infoArr
.join(',')
.match(/(\d{1,2}\/){2}\d{4}/g);
console.log(result);