1
votes

RegExp composite Javascript contenant des sous-RegExps

J'ai écrit un RegExp qui valide correctement une seule devise, par exemple EUR ou USD :

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

Ce qui produit quelque chose comme EUR | USD | JPY | GBP ... avec devises = ["EUR", "USD", "JPY", "GBP" ...] p >

Comment utiliserais-je ce RegExp et le tableau devises comme entrée pour construire un nouveau RegExp qui valide les paires de devises, par exemple EURUSD , USDJPY ?

Le tableau devises est grand et pourrait potentiellement changer, donc je veux créer cette expression régulière dynamiquement, pas coder en dur toutes les permutations possibles de paires de devises.

Les mêmes paires de devises, par exemple, EUREUR et USDUSD ne sont PAS valides.
Les paires de devises dans différents ordres sont valides, par exemple EURUSD et USDEUR.


10 commentaires

De la même façon? curencies = ["EURUSD", "USDJPY"]; ? Ou est-ce la question de savoir comment construire le tableau ["EURUSD", "EURJPY", "USDEUR", "JPYEUR", "USDJPY", "JPYUSD"] avec ["EUR", "USD", "JPY"] comme entrée?


@Shilly désolé si ce n'était pas clair mais le tableau devises est grand et pourrait potentiellement changer, donc je veux créer cette expression régulière dynamiquement, pas coder en dur toutes les permutations possibles des paires de devises


Par conséquent, je demande si vous voulez créer `[" EURUSD "," EURJPY "," USDEUR "," JPYEUR "," USDJPY "," JPYUSD "] avec [" EUR "," USD "," JPY "] comme contribution. Je suppose que c'est un oui?


@Shilly ah oui, avec le tableau devises en entrée, je n'ai malheureusement pas de tableau de paires de devises


D'où provient le tableau des devises ?


L'EUREUR ou l'USDUSD sont-ils valides? L'EURUSD et l'USDEUR sont-ils tous deux possibles?


@Shilly est un service de backend, il n'y a malheureusement pas de service pour récupérer les paires de devises et cela peut prendre un certain temps pour que cela soit construit alors cherchez une solution en attendant


@PJProudhon les mêmes paires de devises ne sont pas valides, les paires de devises dans les deux ordres sont valides


(EUR | USD | JPY | GBP) {2}


@Alexander comme mentionné, voulant une expression régulière créée dynamiquement utilisant un tableau devises , non codé en dur


3 Réponses :


2
votes

Je dirais de garder les choses simples et stupides et de construire un tableau intermédiaire avec toutes les possibilités, exemple:

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

Et gardez votre regex avec ce tableau (vous pouvez également mélanger des devises et des devises pour possibilités) :)


2 commentaires

Je pense que c'est la meilleure solution qui fonctionne pleinement, merci :)


Au moins mettez en cache currency.length dans une variable si vous optez pour cela, sinon ce sera la solution la plus lente. const currency_count = devises.longueur; for (i sinon vous évaluerez la longueur à chaque fois dans la boucle interne et externe.



3
votes

Vous pouvez simplement ajouter {2} pour correspondre exactement à deux éléments de votre ensemble.

Par exemple, / (a ​​| b | c) {2} / code > correspondra à ab , ca mais pas à ad.

Vous pouvez changer votre expression régulière dynamique comme ceci: p>

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

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

Attention: il correspond également à EUREUR . Pour éviter cela, vous devez utiliser un look-behind négatif ou un look-ahead négatif.


Edit

J'intègre l'implémentation @PJProudhon du look-ahead négatif, comme il l'a déclaré dans la section des commentaires:

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'));

Merci @PJProudhon


4 commentaires

Ah bien sûr, et ah oui j'aurais dû mentionner que les mêmes paires de devises ne sont pas valides, mais merci quand même!


Vous n'êtes pas sûr de ce qu'est un look-behind négatif, pouvez-vous modifier votre solution pour l'inclure?


Ou une anticipation négative: comme dans (? :( a | b | c) (?! \ 1)) {2} .


Merci @PJProudhon, j'intègre ton indice dans la réponse



1
votes

C'est un algorithme plutôt inefficace, donc selon la quantité de devises, d'autres options seront meilleures.

Si c'est faisable pour l'ensemble de données, je préférerais la solution de 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 );


0 commentaires