如何使用 javascript 根据字符串进行过滤,同时忽略其中的数字

How to filter based on string while disregarding the number in it using javascript

我有一个要过滤的列列表,现在我正在使用此逻辑:

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

这工作正常,但是,当我有一个巨大的数组时,它会花费很多时间,尤其是 .match 我怎样才能让它更快?使用 .test 或者 .startsWith?

我过滤的 this.columnNames 可以有 ColorColor 1Color 2 等值。这就是为什么我有这样的逻辑:

columnName.match(c + '[ ][0-9]*$'))

它也可以有这样的值:Age RangeAge Range MinimumAge Range Maximum

我想要的是过滤名称和号码,所以在我上面的代码中,颜色,颜色 1... 通过,但 Age Range Minimum 没有。

示例输入:

['Color', 'Color 1', 'Color 2', 'Color 3', 'Age Range', 'Age Range Minimum', 'Age Range Maximum']

示例输出:

['Color', 'Color 1', 'Color 2', 'Color 3']

对于 OP 的用例,一种有效的方法是使用正则表达式,该正则表达式将匹配任何仅由空格分隔的非数字字符序列的字符串。像... /^(?:\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; }

顺便说一句……正则表达式的性能根本不是问题。

下一次过滤两次 70,000 个条目的测试确实证明了这一点(两次不到 7 毫秒)...

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