【问题标题】:Javascript composite RegExp containing sub-RegExpsJavascript 复合正则表达式包含子正则表达式
【发布时间】:2019-03-15 15:28:10
【问题描述】:

我编写了一个正则表达式,它可以正确验证单一货币,例如EURUSD

const ccyRegEx = new RegExp(currencies.join('|'), 'i');

给定currencies = ["EUR", "USD", "JPY", "GBP"...] 会产生类似EUR|USD|JPY|GBP... 的东西

我将如何使用这个 RegExp 和 currencies 数组作为输入来构造一个新的 RegExp 来验证货币对,例如EURUSDUSDJPY

currencies 数组很大,可能会发生变化,所以我想动态创建这个正则表达式,而不是硬编码货币对的所有可能排列。

相同的货币对,例如EUREURUSDUSD 无效。
不同订单的货币对有效,例如EURUSDUSDEUR

【问题讨论】:

  • 同样的方式? curencies = [ "EURUSD", "USDJPY" ]; ?或者问题是如何以["EUR", "USD", "JPY"] 为输入构造数组[ "EURUSD", "EURJPY", "USDEUR", "JPYEUR", "USDJPY", "JPYUSD" ]
  • @Shilly 很抱歉,如果不清楚,但 currencies 数组很大并且可能会发生变化,所以我想动态创建这个正则表达式,而不是硬编码货币对的所有可能排列跨度>
  • 因此我问你是否想用 ["EUR", "USD" 创建 `[ "EURUSD", "EURJPY", "USDEUR", "JPYEUR", "USDJPY", "JPYUSD" ] ", "JPY"] 作为输入。我认为这是肯定的?
  • @Shilly 啊是的,以 currencies 数组作为输入,不幸的是我没有货币对数组
  • 你从哪里得到currencies数组?

标签: javascript regex parsing


【解决方案1】:

您只需添加 {2} 即可完全匹配您的集合中的两个项目。

例如,/(a|b|c){2}/ 将匹配 abca 但不匹配 ad

你可以像这样改变你的动态正则表达式:

const currencies = ["EUR", "USD", "JPY", "GBP"];
const singleMatch = new RegExp(currencies.join('|'));

console.log('single match - EUR:', singleMatch.test('EUR'));

const doubleMatch = new RegExp('(' + currencies.join('|') + '){2}');


console.log('double match - EUR:', doubleMatch.test('EUR'));
console.log('double match - USDEUR:', doubleMatch.test('USDEUR'));
console.log('double match - GBPEUR:', doubleMatch.test('GBPEUR'));
console.log('double match - GBPGDD:', doubleMatch.test('GBPGDD'));

注意:它也匹配EUREUR。为避免这种情况,您应该使用否定的后视或否定的前瞻。


编辑

正如他在 cmets 部分所述,我集成了负前瞻的 @PJProudhon 实现:

const currencies = ["EUR", "USD", "JPY", "GBP"];
const doubleMatch = new RegExp('(?:(' + currencies.join('|') + ')(?!\\1)){2}');

console.log('double match - EUREUR:', doubleMatch.test('EUREUR')); //expect false

谢谢@PJProudhon

【讨论】:

  • 啊,当然,啊,是的,我应该提到相同的货币对无效,​​但无论如何谢谢!
  • 不确定什么是负面的后视,你能编辑你的解决方案来包含它吗?
  • 或负前瞻:如(?:(a|b|c)(?!\1)){2}
  • 谢谢@PJProudhon,我将您的提示整合到答案中
【解决方案2】:

我想说保持简单愚蠢并构建一个具有所有可能性的中间数组,例如:

const currenciesPair = [];
const currenciesLength = currencies.length

for (let i = 0; i < currenciesLength ; i++) {

    for (let j = 0; j < currenciesLength ; j++) {
        // avoiding pair such as EUREUR, USDUSD, etc...
        if (i !== j) {
            currenciesPair.push(currencies[i] + currencies[j]);
        }
    }
}

并将您的正则表达式保留在此数组中(您还可以混合使用 currencyPair 和货币以获得完整的可能性):)

【讨论】:

  • 我认为这是完全有效的最佳解决方案,谢谢 :)
  • 如果你这样做的话,至少在一个变量中缓存currency.length,否则这将是最慢的解决方案。 const currency_count = currencies.length; for ( i &lt; currency_count ) ... 否则,您将在内部和外部循环中每次都评估长度。
【解决方案3】:

不过,这是一种效率相当低的算法,因此根据货币数量,其他选项会更好。

如果数据集可行,我更喜欢 Cristian Traìna 的解决方案。

const currencies = [ "EUR", "USD", "JPY", "GBP" ];

const product_matrix = currencies // loop over all the currencies
	.map( currency => currencies // We want to join the currency with all other currencies
		.map( pair => currency !== pair // Only do the join if the currency and its pair aren't the same
			? `${ currency }${ pair }`
			: null )
		.filter( Boolean ) // Remove all the null values. YOu coudl use reduce instead of map to skip this step.
	)
	.flat(); // Flatten the 2 dimensional array into a one dimensional one.
	
console.log( product_matrix );

【讨论】:

    猜你喜欢
    • 2012-02-13
    • 2012-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-20
    • 2020-02-06
    • 1970-01-01
    相关资源
    最近更新 更多