108 votes

Comment écrire une expression avec opérateur ternaire (alias if) sans se répéter ?

Par exemple, quelque chose comme ça :

var value = someArray.indexOf(3) !== -1 ? someArray.indexOf(3) : 0

Y a-t-il une meilleure façon d'écrire cela ? Encore une fois, je ne cherche pas à obtenir une réponse à la question exacte ci-dessus, juste un exemple de cas où vous pouvez avoir des opérandes répétés dans des expressions d'opérateurs ternaires...

0 votes

Quel type d'intervalle recherchez-vous ? de 1 à ? ou des nombres pairs ou des nombres impairs ou ?

0 votes

Cela ne dépendrait-il pas du fait que la condition ait deux issues différentes, dont aucune n'est identique à la condition elle-même ?

0 votes

C'est juste un exemple. Si une valeur est trouvée, alors donnez la valeur, sinon donnez un 0.

176voto

slebetman Points 28276

Personnellement, je trouve que la meilleure façon de procéder reste le bon vieux if déclaration :

var value = someArray.indexOf(3);
if (value === -1) {
  value = 0;
}

32 votes

Pour être clair, cette réponse préconise l'utilisation d'une variable pour stocker un résultat intermédiaire, pas l'utilisation d'un if à la place d'un ternaire. Les instructions ternaires sont encore fréquemment utiles pour effectuer un choix dans le cadre d'une expression.

5 votes

@Triptych : Regardez-le à nouveau. Il n'utilise pas du tout de variable intermédiaire. Au lieu de cela, il affecte le résultat directement à la variable finale et l'écrase ensuite si la condition est remplie.

14 votes

Incorrect. La valeur stockée dans value après que la première ligne soit intermédiaire. Elle ne contient pas la valeur correcte qui est ensuite fixée sur la ligne suivante et est donc un intermédiaire. Ce n'est qu'après la if La déclaration conclut que value contient la valeur correcte. Le ternaire dans l'OP est une meilleure solution que celle-ci car il n'entre jamais dans un état intermédiaire.

107voto

Dai Points 24530

Le code doit être lisible, donc être succinct ne doit pas signifier être laconique quel qu'en soit le prix - pour cela, vous devez renvoyer à https://codegolf.stackexchange.com/ - donc à la place je recommanderais d'utiliser une seconde variable locale nommée index pour maximiser l'intelligibilité de la lecture (avec un coût d'exécution minimal aussi, je note) :

var index = someArray.indexOf( 3 );
var value = index == -1 ? 0 : index;

Mais si vous voulez vraiment réduire cette expression, parce que vous êtes un sadique cruel envers vos collègues ou collaborateurs de projet, alors voici 4 approches que vous pourriez utiliser :

1 : Variable temporaire dans un var déclaration

Vous pouvez utiliser le var la possibilité pour l'instruction de définir (et d'affecter) une deuxième variable temporaire index lorsqu'ils sont séparés par des virgules :

var index = someArray.indexOf(3), value = index !== -1 ? index: 0;

2 : Fonction anonyme auto-exécutoire

Une autre option est une fonction anonyme auto-exécutoire :

// Traditional syntax:
var value = function( x ) { return x !== -1 ? x : 0 }( someArray.indexOf(3) );

// ES6 syntax:
var value = ( x => x !== -1 ? x : 0 )( someArray.indexOf(3) );

3 : Opérateur de virgule

Il y a aussi le tristement célèbre "opérateur virgule" que JavaScript prend en charge et qui est également présent en C et C++.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator

Vous pouvez utiliser l'opérateur virgule lorsque vous souhaitez inclure plusieurs expressions dans un emplacement qui requiert une seule expression.

Vous pouvez l'utiliser pour introduire des effets de bord, dans ce cas en réassignant à value :

var value = ( value = someArray.indexOf(3), value !== -1 ? value : 0 );

Cela fonctionne parce que var value est interprété en premier (car il s'agit d'une déclaration), et puis le plus à gauche, le plus à l'intérieur value puis la droite de l'opérateur virgule, et enfin l'opérateur ternaire - tout cela est du JavaScript légal.

4 : Réaffectation dans une sous-expression

Le commentateur @IllusiveBrian a fait remarquer que l'utilisation de l'opérateur virgule (dans l'exemple précédent) est inutile si l'affectation à value est utilisé comme une sous-expression entre parenthèses :

var value = ( ( value = someArray.indexOf(3) ) !== -1 ? value : 0 );

Notez que l'utilisation de la négation dans les expressions logiques peut être plus difficile à suivre pour les humains - ainsi tous les exemples ci-dessus peuvent être simplifiés pour la lecture en changeant idx !== -1 ? x : y à idx == -1 ? y : x :

var value = ( ( value = someArray.indexOf(3) ) == -1 ? 0 : value );

99 votes

Ce sont tous des codes "intelligents" qui m'obligent à les regarder quelques secondes avant de me dire : "Je suppose que ça marche". Ils n'aident pas à la clarté, et puisque le code est lu plus qu'il n'est écrit, c'est plus important.

18 votes

L'approche 1 de @g.rocket est 100% lisible et claire, et c'est la seule façon de procéder si vous voulez éviter les répétitions (qui pourraient être vraiment dommageables si vous appelez une fonction complexe et problématique au lieu d'une simple indefOf )

5 votes

Je suis d'accord, le numéro 1 est très lisible et facile à maintenir, les deux autres pas vraiment.

54voto

Crisoforo Gaspar Points 2333

Pour les chiffres

Vous pouvez utiliser le Math.max() fonction.

var value = Math.max( someArray.indexOf('y'), 0 );

Cela empêchera les limites du résultat de 0 jusqu'à ce que le premier résultat supérieur à 0 si c'est le cas. Et si le résultat de indexOf es -1 il retournera 0 car il est supérieur à -1 .

Pour les booléens et les valeurs booléennes-y

Pour JS il n'y a pas de règle générale AFAIK surtout parce que comment falsy sont évaluées.

Mais si quelque chose peut vous aider la plupart du temps est l'opérateur ou ( || ):

// Instead of
var variable = this_one === true ? this_one : or_this_one;
// you can use
var variable = this_one || or_this_one;

Il faut être très prudent avec ça, car dans votre premier exemple, indexOf peut retourner 0 et si vous évaluez 0 || -1 il retournera -1 parce que 0 est un falsy valeur.

2 votes

Merci. Je suppose que mon exemple est mauvais. Je donne juste un exemple général et je ne cherche pas à trouver une solution à la question exacte. J'ai été confronté à des scénarios comme celui où je voudrais utiliser un ternaire, mais où je finis par répéter :(

1 votes

Au premier exemple, comment déterminer que 3 o "y" n'est pas à l'index 0 de someArray ?

0 votes

Sur le Math.max exemple ? indexOf renvoie l'index de l'élément et si l'élément n'est pas trouvé, il renvoie -1. Vous avez donc une chance d'obtenir un nombre compris entre -1 et la longueur de la chaîne, puis avec Math.max il suffit de définir les limites de 0 à la longueur pour éliminer la possibilité de retourner un -1,

27voto

Triptych Points 70247

Pas vraiment, il suffit d'utiliser une autre variable.

Votre exemple se généralise à quelque chose comme ça.

var x = predicate(f()) ? f() : default;

Vous testez une valeur calculée, puis vous affectez cette valeur à une variable si elle passe un certain prédicat. La façon d'éviter de recalculer la valeur calculée est évidente : utiliser une variable pour stocker le résultat.

var computed = f();
var x = predicate(computed) ? computed : default;

Je comprends ce que vous voulez dire - il semble qu'il devrait y avoir un moyen de faire cela qui soit un peu plus propre. Mais je pense que c'est la meilleure façon (idiomatiquement) de le faire. Si, pour une raison quelconque, vous répétiez souvent ce modèle dans votre code, vous pourriez écrire une petite fonction d'aide :

var setif = (value, predicate, default) => predicate(value) ? value : default;
var x = setif(someArray.indexOf(3), x => x !== -1, 0)

20voto

Lyubomir Points 10274

EDIT : La voici, la proposition de Coalescence nullaire maintenant en JavaScript !


Utilice ||

const result = a ? a : 'fallback value';

est équivalent à

const result = a || 'fallback value';

Si le casting a à Boolean renvoie à false , result sera attribué 'fallback value' sinon la valeur de a .


Attention au cas limite a === 0 ce qui donne lieu à false y result prendra (incorrectement) 'fallback value' . Utilisez ce genre d'astuces à vos risques et périls.


_PS. Des langages comme Swift ont pas de coalescence opérateur ( ?? ), qui sert un objectif similaire. Par exemple, en Swift, vous écrirez result = a ?? "fallback value" qui est assez proche de la méthode JavaScript const result = a || 'fallback value';_

3 votes

PHP (>7.0) et C# prennent également en charge l'opérateur de coalescence nul. Du sucre syntaxique mais sûrement charmant.

5 votes

Cela ne fonctionne que si la fonction renvoie une fausse valeur lorsqu'elle échoue, mais indexOf() ne peut pas être utilisé dans ce modèle.

1 votes

C'est exact, mais il ne demande pas l'exemple spécifique > "Encore une fois, je ne cherche pas à répondre à la question exacte ci-dessus, juste un exemple de cas où vous auriez pu répéter des choses dans le ternaire" <, attention, il demande plutôt un moyen générique de remplacer la répétition du ternaire (résultat = a ? a : b). Et le ternaire répété est équivalent à || (result = a || b)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X