【问题标题】:How to define an array with conditional elements?如何定义具有条件元素的数组?
【发布时间】:2017-12-08 01:20:19
【问题描述】:

如何定义条件数组元素? 我想做这样的事情:

const cond = true;
const myArr = ["foo", cond && "bar"];

这按预期工作并导致["foo", "bar"],但如果我将cond 设置为false,我会得到以下结果:["foo", false]

如何定义带有条件元素的数组?

【问题讨论】:

标签: javascript arrays


【解决方案1】:

当条件为false时,您可以在数组内部展开数组,以保持items数组干净。

您可以这样做

// Will result in ['foo', 'bar']
const items = [
  'foo',
  ... true ? ['bar'] : [],
  ... false ? ['falsy'] : [],
]

console.log(items)

解释

如您所见,三元运算符总是返回一个数组。

如果条件为true,则返回['bar'],否则为空数组[]

之后,我们将... 得到的数组(来自三元运算)展开,并将数组的项推送到父数组。

如果没有任何数组项(当三元检查为false时),则不会推送任何内容,这是我们的目标。


在其他答案中,我解释了相同的想法,但针对对象。你也可以查看here

【讨论】:

  • 我最近需要这样做,而使用 spread 对我来说似乎是最明显的解决方案。很高兴其他人也在使用这种模式。我不想让它太神秘,但我会继续使用它,因为它看起来足够流行。
  • 非常感谢~!!我只是没有考虑将点差作为一种选择
  • 这很酷,没想到事后不过滤数组也能做到这一点
  • 这就是我喜欢 Ecmascript 的原因
  • 优秀的解决方案!
【解决方案2】:

我会这样做

[
  true && 'one',
  false && 'two',
  1 === 1 && 'three',
  1 + 1 === 9 && 'four'
].filter(Boolean) // ['one', 'three']

请注意,这也会删除 falsy 值,例如空字符串。

【讨论】:

  • 我喜欢这个主意。但是对于 [ true && ''],您的实现将是错误的。空字符串将被过滤掉。我宁愿使用像 [foo].filter(isNonBoolean) 或 [foo].stripBoolean() 这样的辅助函数
  • @Martin 是的,也许可以在答案中详细说明。我会继续编辑它!
  • 我认为如果我需要这样的数组会有问题: const arr = ['one', 'two', false, true];但是想法有利于真实的价值:)
  • 如果您有条件地将元素添加到具有子项(例如 ListView、Column、Row)的 Widget,这将不起作用,并说“运算符的操作数 '&&' 必须可分配给 bool .".
【解决方案3】:

你可以尝试一个简单的 if :

if(cond) {
    myArr.push("bar");
}

【讨论】:

  • OP 明确要求以声明性方式执行此操作,而不是强制方式。
【解决方案4】:

如果您真的想将其保留为一个衬里,您可以使用:

const cond = true;
const myArr = ["foo"].concat(cond ? ["bar"] : []);

【讨论】:

  • 聪明,对我来说对数组的条件前面很有用,即const myArr = (cond ? ['item 1'] : []).concat(['item 2', 'item 3']);
【解决方案5】:

除了使用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);

【讨论】:

    【解决方案6】:
    const cond = false;
    const myArr = ["foo", cond ? "bar" : null].filter(Boolean);
    
    console.log(myArr)
    

    将导致 ["foo"]

    【讨论】:

      【解决方案7】:

      有几种不同的方式,但你的方式并不真正适用于 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 但你是对的,它可能是垃圾。但是很酷的垃圾;)
      • 这很酷,但我建议不要只使用一个条件值。它更适合通用的“摆脱所有错误值”类型的东西。因为您最终将只为一个值遍历整个数组。但是,如果您有未确定数量的条件值,那么它可能是一个很好的解决方案。
      • .filter(e => e) 会过滤掉空字符串。
      【解决方案8】:

      有条件地添加元素

      /**
       * 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;
          }, [])
      );
      
      

      【讨论】:

        【解决方案9】:

        如果您不太关心性能并且感觉您想了解更多关于 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']
        

        【讨论】:

          【解决方案10】:

          替代方法:预过滤填充而不是后过滤:

          const populate = function(...values) {
              return values.filter(function(el) {
                  return el !== false
              });
          };
          
          console.log(populate("foo", true && "bar", false && "baz"))
          

          返回

          (2) ["foo", "bar"]
          

          我知道这并不能解决速记符号(因为无论您尝试什么都行不通),但它已经接近了。

          【讨论】:

            【解决方案11】:

            如果你使用的是 es6,我会建议

            let array = [ "bike", "car", name === "van" ? "van" : null, "bus", "truck", ].filter(Boolean);

            如果name等于“van”,这个数组将只包含值“van”,否则将被丢弃。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2019-11-27
              • 1970-01-01
              • 1970-01-01
              • 2017-10-11
              • 2020-01-31
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多