例如,像这样:
foo
有更好的方式来写吗?同样,我不是在寻找上面确切问题的答案,只是你可能在三元运算符表达式中重复操作数的例子......
答案 0 :(得分:175)
就我个人而言,我发现最好的方法仍然是好的旧if
声明:
var value = someArray.indexOf(3);
if (value === -1) {
value = 0;
}
答案 1 :(得分:97)
代码应该是可读的,所以简洁并不意味着要花费任何成本 - 因为你应该重新发布到https://codegolf.stackexchange.com/ - 所以我建议使用名为index
的第二个局部变量来最大化阅读可理解性(运行成本也很低,我注意到):
var index = someArray.indexOf( 3 );
var value = index == -1 ? 0 : index;
但如果你真的想减少这种表达,因为你对你的同事或项目合作者来说是一个残酷的虐待狂,那么你可以使用以下四种方法:
var
语句中的临时变量当用逗号分隔时,您可以使用var
语句定义(和分配)第二个临时变量index
的能力:
var index = someArray.indexOf(3), value = index !== -1 ? index: 0;
另一种选择是自动执行匿名函数:
// 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) );
还有臭名昭着的逗号运营商" JavaScript支持哪些,它也存在于C和C ++中。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator
如果要在需要单个表达式的位置包含多个表达式,可以使用逗号运算符。
您可以使用它来引入副作用,在这种情况下,通过重新分配到value
:
var value = ( value = someArray.indexOf(3), value !== -1 ? value : 0 );
这是有效的,因为var value
首先被解释(因为它是一个声明),然后是最左边的,最里面的value
赋值,然后逗号运算符的右侧,然后是三元运算符 - 所有合法的JavaScript。
评论员@IllusiveBrian指出,如果将value
的赋值用作带括号的子表达式,则不需要使用逗号运算符(在前面的示例中):
var value = ( ( value = someArray.indexOf(3) ) !== -1 ? value : 0 );
请注意,在逻辑表达式中使用否定词对于人类来说可能更难以遵循 - 因此,通过将idx !== -1 ? x : y
更改为idx == -1 ? y : x
,可以简化以上所有示例以进行阅读:
var value = ( ( value = someArray.indexOf(3) ) == -1 ? 0 : value );
答案 2 :(得分:53)
数字
您可以使用Math.max()
功能。
var value = Math.max( someArray.indexOf('y'), 0 );
如果是这种情况,它将保留0
结果的边界,直到第一个结果大于0
。如果indexOf
的结果为-1
,则会返回0,大于-1
。
对于布尔值和布尔值y
对于JS,没有一般规则AFAIK,因为如何评估falsy值。
但是如果有什么东西可以帮助你,那么大部分时间都是or运算符(||
):
// Instead of
var variable = this_one === true ? this_one : or_this_one;
// you can use
var variable = this_one || or_this_one;
您必须非常小心,因为在您的第一个示例中,indexOf
可以返回0
,如果您评估0 || -1
,它将返回-1
,因为{{ 1}}是falsy值。
答案 3 :(得分:26)
不是,只是使用另一个变量。
你的例子概括为类似的东西。
var x = predicate(f()) ? f() : default;
您正在测试计算值,然后在传递某个谓词时将该值分配给变量。避免重新计算计算值的方法很明显:使用变量来存储结果。
var computed = f();
var x = predicate(computed) ? computed : default;
我理解你的意思 - 似乎应该有一些方法来做这个看起来更清洁的方法。但我认为这是实现这一目标的最佳方式(惯用)。如果由于某种原因你在代码中重复了这个模式,你可能会写一个小帮助函数:
var setif = (value, predicate, default) => predicate(value) ? value : default;
var x = setif(someArray.indexOf(3), x => x !== -1, 0)
答案 4 :(得分:17)
使用||
const result = a ? a : 'fallback value';
相当于
const result = a || 'fallback value';
如果将a
投放到Boolean
返回false
,则会为result
分配'fallback value'
,否则为a
。 强>
请注意边缘情况a === 0
,其转换为false
,result
将(错误地)转为'fallback value'
。使用这样的技巧需要您自担风险。
PS。 Swift等语言具有nil-coalescing运算符(??
),其用途类似。例如,在Swift中你会写result = a ?? "fallback value"
,它非常接近JavaScript的const result = a || 'fallback value';
答案 5 :(得分:8)
使用extract variable refactoring:
var index = someArray.indexOf(3);
var value = index !== -1 ? index : 0
使用const
代替var
会更好。您还可以进行额外的提取:
const index = someArray.indexOf(3);
const condition = index !== -1;
const value = condition ? index : 0;
在实践中,使用比index
,condition
和value
更有意义的名称。
const threesIndex = someArray.indexOf(3);
const threeFound = threesIndex !== -1;
const threesIndexOrZero = threeFound ? threesIndex : 0;
答案 6 :(得分:6)
我个人更喜欢两种变体:
如果像@slebetman建议那样纯粹
单独的函数,用默认值替换无效值,如下例所示:
function maskNegative(v, def) {
return v >= 0 ? v : def;
}
Array.prototype.indexOfOrDefault = function(v, def) {
return maskNegative(this.indexOf(v), def);
}
var someArray = [1, 2];
console.log(someArray.indexOfOrDefault(2, 0)); // index is 1
console.log(someArray.indexOfOrDefault(3, 0)); // default 0 returned
console.log(someArray.indexOfOrDefault(3, 123)); // default 123 returned
答案 7 :(得分:6)
您可能正在寻找一个合并运营商。幸运的是,我们可以利用Array
原型创建一个:
Array.prototype.coalesce = function() {
for (var i = 0; i < this.length; i++) {
if (this[i] != false && this[i] != null) return this[i];
}
}
[null, false, 0, 5, 'test'].coalesce(); // returns 5
通过向函数添加参数,可以进一步推广这种情况:
Array.prototype.coalesce = function(valid) {
if (typeof valid !== 'function') {
valid = function(a) {
return a != false && a != null;
}
}
for (var i = 0; i < this.length; i++) {
if (valid(this[i])) return this[i];
}
}
[null, false, 0, 5, 'test'].coalesce(); // still returns 5
[null, false, 0, 5, 'test'].coalesce(function(a){return a !== -1}); // returns null
[null, false, 0, 5, 'test'].coalesce(function(a){return a != null}); //returns false
答案 8 :(得分:5)
我喜欢@ slebetman的回答。其中的评论表达了对变量处于“中间状态”的担忧。如果这是你的一个大问题,那么我建议将其封装在一个函数中:
function get_value(arr) {
var value = arr.indexOf(3);
if (value === -1) {
value = 0;
}
return value;
}
然后致电
var value = get_value( someArray );
如果你在其他地方使用它们,你可以做更多的通用功能,但如果它是一个非常具体的情况,不要过度工程。
但说实话,我会像@slebetman一样做,除非我需要从几个地方重新使用。
答案 9 :(得分:4)
我可以通过两种方式查看您的问题:您要么想减少行长度,要么特别想避免在三元组中重复变量。第一个是微不足道的(许多其他用户已发布示例):
var value = someArray.indexOf(3) !== -1 ? someArray.indexOf(3) : 0;
可以(并且应该在给定函数调用的情况下)缩短为:
var value = someArray.indexOf(3);
value = value !== -1 ? value : 0;
如果您正在寻找一种更通用的解决方案,以防止在三元组中重复变量,例如:
var value = conditionalTest(foo) ? foo : bar;
其中foo
只出现一次。丢弃表格的解决方案:
var cad = foo;
var value = conditionalTest(foo) ? cad : bar;
虽然技术上正确但却忽略了重点,那么你运气不好。有些操作符,函数和方法都拥有您所寻求的简洁语法,但根据定义,这些结构不是三元运算符。
示例:
javascript,当LHS为||
时使用falsey
返回RHS:
var value = foo || bar; // equivalent to !foo ? bar : foo
答案 10 :(得分:3)
使用帮助函数:
function translateValue(value, match, translated) {
return value === match ? translated : value;
}
现在你的代码非常易读,而且没有重复。
var value = translateValue(someArray.indexOf(3), -1, 0);
编码问题的层次结构是:
到目前为止,页面上的所有答案似乎都是正确的,但我认为我的版本具有最高的清晰度,这比简洁更重要。如果你不计算辅助函数 - 因为它可以重用 - 它也是最简洁的。不幸的是,使用辅助函数的一些类似建议使用了一个lambda,对我而言,它只是掩盖了它正在做的事情。一个更简单的函数有一个目的,不需要lambda,只是值,对我来说更好。
P.S。如果您喜欢ES6语法:
const translateValue = (value, match, translated) => value === match ? translated : value;
let value = translateValue(someArray.indexOf(3), -1, 0); // or const
答案 11 :(得分:2)
我认为||
运算符可以定制为indexOf
:
var value = ((someArray.indexOf(3) + 1) || 1) - 1;
返回的值向上移动1,从-1开始为0,这是假的,因此被第二个1替换。然后它被移回。
但是,请记住,可读性优于避免重复。
答案 12 :(得分:2)
这是一个简单的解决方案bitwise NOT,默认值为-1
,后来会产生零。
index = ~(~array.indexOf(3) || -1);
它基本上使用双按位NOT,它返回原始值或默认值,在应用按位NOT后返回零。
让我们看看真相表:
indexOf ~indexOf boolean default value result comment --------- --------- --------- --------- --------- --------- ------------------ -1 0 falsy -1 -1 0 take default value 0 -1 truthy -1 0 1 -2 truthy -2 1 2 -3 truthy -3 2
答案 13 :(得分:0)
鉴于问题中的示例代码,不清楚如何确定3
是否设置在0
的索引someArray
。从-1
返回的.indexOf()
在这种情况下很有价值,目的是排除可能匹配的推定不匹配。
如果数组中未包含3
,则会返回-1
。我们可以将1
添加到.indexOf()
的结果,以评估结果为false
为-1
,其后是||
OR
运算符和{{ 1}}。引用0
时,减去value
以获取数组元素的索引或1
。
这导致简单地使用-1
并在.indexOf()
条件下检查-1
。或者,将if
定义为value
,以避免可能混淆与原始参考相关的评估条件的实际结果。
undefined
&#13;
答案 14 :(得分:0)
您可以使用重新分配:
&&
运算符的序列化进行重新分配,因为如果第一个条件为false,则不会计算第二个表达式实施例
var value = someArray.indexOf(3);
value == -1 && (value=0);
var someArray = [4,3,2,1];
var value = someArray.indexOf(1);
value == -1 && (value=0);
console.log('Found:',value);
var value = someArray.indexOf(5);
value == -1 && (value=0);
console.log('Not Found:',value);
答案 15 :(得分:0)
三元就像是if-else,如果你不需要其他部分,为什么不只是一个而不是..
if ((value = someArray.indexOf(3)) < 0) value = 0;
答案 16 :(得分:0)
对于这种特殊情况,您可以使用逻辑||
运算符进行短路。由于0
被认为是虚假的,因此您可以+1
进入索引,因此,如果index+1
为0
,那么您将获得回报的右侧结果,否则,您将得到index+1
。然后,您可以根据此结果-1
来获取索引:
const someArray = [1, 2, 3, 4];
const v = ((someArray.indexOf(3)+1) || 1)-1;
console.log(v);