【发布时间】:2017-12-08 01:20:19
【问题描述】:
如何定义条件数组元素? 我想做这样的事情:
const cond = true;
const myArr = ["foo", cond && "bar"];
这按预期工作并导致["foo", "bar"],但如果我将cond 设置为false,我会得到以下结果:["foo", false]
如何定义带有条件元素的数组?
【问题讨论】:
标签: javascript arrays
如何定义条件数组元素? 我想做这样的事情:
const cond = true;
const myArr = ["foo", cond && "bar"];
这按预期工作并导致["foo", "bar"],但如果我将cond 设置为false,我会得到以下结果:["foo", false]
如何定义带有条件元素的数组?
【问题讨论】:
标签: javascript arrays
当条件为false时,您可以在数组内部展开数组,以保持items数组干净。
您可以这样做:
// Will result in ['foo', 'bar']
const items = [
'foo',
... true ? ['bar'] : [],
... false ? ['falsy'] : [],
]
console.log(items)
解释:
如您所见,三元运算符总是返回一个数组。
如果条件为true,则返回['bar'],否则为空数组[]。
之后,我们将... 得到的数组(来自三元运算)展开,并将数组的项推送到父数组。
如果没有任何数组项(当三元检查为false时),则不会推送任何内容,这是我们的目标。
在其他答案中,我解释了相同的想法,但针对对象。你也可以查看here。
【讨论】:
我会这样做
[
true && 'one',
false && 'two',
1 === 1 && 'three',
1 + 1 === 9 && 'four'
].filter(Boolean) // ['one', 'three']
请注意,这也会删除 falsy 值,例如空字符串。
【讨论】:
你可以尝试一个简单的 if :
if(cond) {
myArr.push("bar");
}
【讨论】:
如果您真的想将其保留为一个衬里,您可以使用:
const cond = true;
const myArr = ["foo"].concat(cond ? ["bar"] : []);
【讨论】:
const myArr = (cond ? ['item 1'] : []).concat(['item 2', 'item 3']);
除了使用push之外,您没有太多选择:
const cond = true;
const myArr = ["foo"];
if (cond) myArr.push("bar");
另一个想法可能是添加空值并将它们过滤掉:
const cond = true;
const myArr = ["foo", cond ? "bar" : null];
myArr = myArr.filter((item) => item !== null);
【讨论】:
const cond = false;
const myArr = ["foo", cond ? "bar" : null].filter(Boolean);
console.log(myArr)
将导致 ["foo"]
【讨论】:
有几种不同的方式,但你的方式并不真正适用于 Javascript。
最简单的解决方案是只使用一个 if 语句。
if (myCond) arr.push(element);
还有filter,但我认为这根本不是你想要的,因为你似乎想要“添加这件事,如果这一个条件为真”而不是根据某个条件检查所有内容.虽然,如果你想变得非常古怪,你可以这样做(不推荐,但你可以这样做很酷)。
var arr = ["a", cond && "bar"];
arr.filter( e => e)
基本上它只会过滤掉所有非真值。
【讨论】:
var arr = ["a", cond && "bar"].filter(e => e);@Adam LeBlanc 但你是对的,它可能是垃圾。但是很酷的垃圾;)
/**
* Add item to array conditionally.
* @param {boolean} condition
* @param {*} value new item or array of new items
* @param {boolean} multiple use value as array of new items (for future)
* @returns {array} array to spread
* @example [ ...arrayAddConditionally(true, 'foo'), ...arrayAddConditionally(false, 'bar'), ...arrayAddConditionally(true, [1, 2, 3]), ...arrayAddConditionally(true, [4, 5, 6], true) ] // ['foo', [1, 2, 3], 4, 5, 6]
*/
export const arrayAddConditionally = (condition, value, multiple) => (
condition
? multiple ? value : [value]
: []
);
/**
* Create array with conditional elements
* @typedef {[condition: boolean, value: any, multiple: boolean]} ConditionalElement
* @param {(ConditionalElement|*)[]} map non-array element will be added as it is, array element must allways be conditional
* @returns {array} new array
* @example createArrayConditionally([[true, 'foo'], [false, 'baz'], [true, [1, 2, 3]], [true, [4, 5, 6], true], {}]) // ['foo', [1,2,3], 4, 5, 6, {}]
*/
export const createArrayConditionally = (map) => (
map.reduce((newArray, item) => {
// add non-conditional as it is
if (!Array.isArray(item)) {
newArray.push(item);
} else {
const [condition, value, multiple] = item;
// if multiple use value as array of new items
if (condition) newArray.push[multiple ? 'apply' : 'call'](newArray, value);
}
return newArray;
}, [])
);
【讨论】:
如果您不太关心性能并且感觉您想了解更多关于 Javascript 的信息,这是 Jordan Enev 的答案的替代方案 :)
所以,如果你想这样做,但没有 false/undefined/null 元素
['foo', true && 'bar', null && 'baz']; // ['foo', 'bar', null]
你可以这样做:
['foo', true && 'bar', ...Object.values({ ...(null && ['baz']) })]; // ['foo', 'bar']
最后,肯定条件会按预期工作:
['foo', true && 'bar', ...Object.values({ ...(true && ['baz']) })]; // ['foo', 'bar', 'baz']
奖励:如果你想向数组中添加一个东西,但这个东西可以是falsy,然后你不希望它在那里,不做第二次操作,这里有一种方法:
const foo = 1; // 1
const bar = (() => 'expensive result that turns out falsy for bar' && false)(); // false
const baz = (() => 'expensive result for baz')(); // 'expensive result'
const conditionalArrayWrapperFor = i => i ? [i] : [];
// tip: you can always inline conditionalWrapper if you only execute it once
// for instance, if you're using this inside a reduce call
[foo, ...conditionalArrayWrapperFor(bar), ...conditionalArrayWrapperFor(baz)] // [1, 'expensive result for baz']
【讨论】:
替代方法:预过滤填充而不是后过滤:
const populate = function(...values) {
return values.filter(function(el) {
return el !== false
});
};
console.log(populate("foo", true && "bar", false && "baz"))
返回
(2) ["foo", "bar"]
我知道这并不能解决速记符号(因为无论您尝试什么都行不通),但它已经接近了。
【讨论】:
如果你使用的是 es6,我会建议
let array = [
"bike",
"car",
name === "van" ? "van" : null,
"bus",
"truck",
].filter(Boolean);
如果name等于“van”,这个数组将只包含值“van”,否则将被丢弃。
【讨论】: