I have a list of columns that I want to filter, right now I'm using this logic:
for (const columnName of this.columnNames) {
const matchingColumns = fieldsForSearch.filter(c => columnName === c ||
columnName.match(c + '[ ][0-9]*$'));
if (matchingColumns && matchingColumns.length > 0) {
// do something...
}
}
This is working fine, however, when I have a huge array it's taking a lot of time, especially the .match How can I make it faster? Using .test or maybe .startsWith?
The this.columnNames I'm filtering on can have values like Color, Color 1, Color 2, etc. This is why I have the logic:
columnName.match(c + '[ ][0-9]*$'))
It can also have values like this: Age Range, Age Range Minimum, Age Range Maximum.
What I want is to filter the name and the number, so in my code above Color, Color 1... passes but Age Range Minimum doesn't.
Sample input:
['Color', 'Color 1', 'Color 2', 'Color 3', 'Age Range', 'Age Range Minimum', 'Age Range Maximum']
Sample output:
['Color', 'Color 1', 'Color 2', 'Color 3']
For the OP's use case a valid approach was to use a regex which will match any string wich is a sequence of whitespace separated non digit characters only. Something like ... /^(?:\D+\s+\D+)(?:\s+\D+)*$/ ... Thus one matches exactly those strings, the OP wants to reject. A filter function then uses the negated return value of RegExp.prototype.test ...
const sampleInput = ['Color', 'Color 1', 'Color 2', 'Color 3', 'Age Range', 'Age Range Minimum', 'Age Range Maximum'];
const expectedResult = ['Color', 'Color 1', 'Color 2', 'Color 3'];
// matches any string wich is a sequence of
// whitespace separated non digit characters.
// see ... [https://regex101.com/r/6EBe7U/1/]
const regXWsSeparatedNonDigitSequence = (/^(?:\D+\s+\D+)(?:\s+\D+)*$/);
console.log(
sampleInput, ' =>',
sampleInput.filter(item =>
!regXWsSeparatedNonDigitSequence.test(item)
)
);
console.log(
'test passed ?',
sampleInput.filter(item =>
!regXWsSeparatedNonDigitSequence.test(item)
).join(',') === expectedResult.join(',')
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
btw ... regex performance is not an issue at all.
The next test which filters two times 70,000 entries does prove it (two time less than 7msec) ...
const regXWsSeparatedNonDigitSequence = (/^(?:\D+\s+\D+)(?:\s+\D+)*$/);
let testData = new Array(10_000);
let result;
// create an array of 70_000 string entries (10_000 x 7(string item count))
testData = testData
.fill(['Color', 'Color 1', 'Color 2', 'Color 3', 'Age Range', 'Age Range Minimum', 'Age Range Maximum'])
.flat(1);
// test with regex reference.
console.time("70,000 regX tests (reference) :: filter duration");
result = testData.filter(item =>
!regXWsSeparatedNonDigitSequence.test(item)
)
console.timeEnd("70,000 regX tests (reference) :: filter duration");
console.log('test passed ?.. ', (result.length === 40_000));
// test with regex literal.
console.time("70,000 regX tests (literal) :: filter duration");
result = testData.filter(item =>
!(/^(?:\D+\s+\D+)(?:\s+\D+)*$/).test(item)
)
console.timeEnd("70,000 regX tests (literal) :: filter duration");
console.log('test passed ?.. ', (result.length === 40_000));
.as-console-wrapper { min-height: 100%!important; top: 0; }