【问题标题】:Adding an object conditionally inside an array在数组内有条件地添加对象
【发布时间】:2021-11-24 21:03:41
【问题描述】:

我想在对象数组中添加一个条件对象。如果条件不满足,我希望该对象根本不存在,而其他对象保持原样。 考虑以下几点:

const CardBuildingBlock: FC = () => {
    const type = 'typeA';

    const typesOfCards = [
      {name: 'Card A'
      size: 'Medium'
      action: 'make'},

      {name: 'Card B'
      size: 'Small'
      action: 'break'},

      {name: 'Card C'
      size: 'Large'
      action: 'build'},

//我尝试了以下操作,但没有成功

      type == 'typeA' ? null : {
      name: 'Card A'
      size: 'Medium'
      action: 'make'},
    ];


    return(
      typeOfCards.map(({name, size, action}) => (
        <BuildCard 
          name = {name}
          size = {size}
          action = {action}
        />
    )
)};

请帮忙!!!!

感谢您的帮助。

【问题讨论】:

  • 我不是 100% 确定你的意图,但听起来你想filter 数组在你之前map
  • 不要在数组中保存 nullundefined 值。删除它们或不添加它们
  • 为什么在数组创建后不这样做。创建typesOfCards 后,执行条件部分。

标签: javascript reactjs typescript next.js


【解决方案1】:

据我了解,您希望在给定条件的情况下过滤掉数组的所有元素。我要做的是向对象添加一个新键,指定是否应该显示它,然后过滤和映射。

const typesOfCards = [
  { name: "Card A", size: "Medium", action: "make", type: "typeA" },
  ...
];
return typesOfCards.filter(card => card.type === "typeA").map(({ name, size, action }) => (
    <BuildCard name={name} size={size} action={action} />
  ));

【讨论】:

  • 返回 typesOfCards.filter(card => card.type === "typeA").map(({ name, size, action }) => ( ));当你写 card => card.type ...你的意思是 typesOfCards => typesOfCards.type 吗?还是您的意思是在过滤器中创建一个新变量?
  • 我将字段类型添加到所有卡片中。所以所有的卡片都应该有一个值为 typeA、typeB 或其他值的字段类型。这样,当您过滤时,您可以使用该字段删除所有不属于给定类型的字段。我本可以将其命名为 filter(typeOfCard => typeOfCard.type... 但它只是变量的名称
  • 我现在明白了。谢谢,罗伯特。另一个跟进:我如何有条件地过滤?如何在 type == 'typeA' 时显示卡片 a、b 和 c,但在 type == 'typeB' 时只有卡片 a 和 c?
  • 如果 type=='typeA' 你想同时显示 a、b 和 c...这意味着我不会使用过滤器,因为你想要所有。
  • 如果 type=='typeB' 你只想显示 a 和 c... 然后我会做 filter(card => card.type === 'typeA' || card.type === '类型C)。请注意,我使用新的字段类型作为助手,以便我知道如何过滤卡片。也许根据您的业务规则,您可以有另一个过滤器
【解决方案2】:

这里最简单的方法是将concat 新元素添加到数组中。如果条件为真,您将连接新元素。考虑这个例子:

// using if statement
const type = "typeA";

let additionalCardOfTypeA = {
  name: "Card A",
  size: "Medium",
  action: "make",
};

let typesOfCards = [
  { name: "Card A", size: "Medium", action: "make" },
  { name: "Card B", size: "Small", action: "break" },
  { name: "Card C", size: "Large", action: "build" },
];

if (type === "typeA") {
  typesOfCards = typesOfCards.concat(additionalCardOfTypeA);
}
// using ternary operator
const type = "typeA";

let additionalCardOfTypeA = {
  name: "Card A",
  size: "Medium",
  action: "make",
};

let typesOfCards = [
  { name: "Card A", size: "Medium", action: "make" },
  { name: "Card B", size: "Small", action: "break" },
  { name: "Card C", size: "Large", action: "build" },
].concat(
  type === "typeA"
    ? additionalCardOfTypeA 
    : []
);

编辑

要在特定位置插入新元素,您必须创建额外的数组。首先,为您的元素找到一个位置。然后,创建一个包含原始索引之前的所有内容的数组,以及包含从索引到结尾的所有内容的数组。然后将开始、新元素和结束连接到最终数组中。

const type = "typeA";

let additionalCardOfTypeA = {
  name: "Card A",
  size: "Medium",
  action: "make",
};

let typesOfCards = [
  { name: "Card A", size: "Medium", action: "make" },
  { name: "Card B", size: "Small", action: "break" },

  { name: "Card C", size: "Large", action: "build" },
];

if (type === "typeA") {
  let indexForNewElement = getSomehowIndex();
  // Getting everything before index
  let head = typesOfCards.slice(0, indexForNewElement);
  // Getting everything after index
  let tail = typesOfCards.slice(indexForNewElement);
  typesOfCards = head.concat(additionalCardOfTypeA).concat(tail);
}

【讨论】:

  • 您的意思是push 而不是concat,对吗? (至少在您的第一个示例中。您的第二个示例可以工作,但连接一个空数组不做任何事情也感觉有点奇怪。)
  • 我同意。推是一个更好的方式去这里,海事组织。但是如果我希望该对象位于数组内的特定索引上,我将如何使用 push。例如,如果/当条件为真时,我希望卡 B 在卡 A 之后立即执行(它应该出现在卡 A 和 C 之间,或者根本不应该出现)。使用 push 只会在最后添加它。有没有办法使用推送来做到这一点?
  • 不,我的意思是concatconcat 将创建新数组,因此初始数据不会发生变异。在这个特定的示例中,所有数据都在同一位置并在每次渲染时创建了新数组,但如果初始数组来自道具或其他地方,则不能使用 push 并对其进行变异。从一开始就使用 concat 可以让您移动初始数组,而不必担心不可变性。在 concat 中使用空数组确实可能看起来很奇怪,但这只是为了三元运算符,就像在初始代码中一样。我会亲自使用 if 语句。
  • 我将在答案中添加将元素添加到任意位置的示例
  • 抱歉,我的印象是 concat 仅在参数是数组时才有效,但是在更深入地咨询了 MDN(并在控制台中尝试过)后,我发现 concat 而不是 push 会起作用美好的。谢谢你教我一些我不知道的关于 JS 的东西:)
【解决方案3】:

在这种情况下,推送可能会很有用:

type === 'typeA' && typesOfCards.push({
      name: 'Card A'
      size: 'Medium'
      action: 'make'}
)

也许你可能想在一个函数中包含它,它应该返回 typesOfCards 数组

【讨论】:

  • 太棒了。我实际上可以使用推送,但在某些情况下,我会要求对象位于特定索引处。例如,如果/当条件为真时,我希望卡 B 在卡 A 之后立即执行。使用 push 只会在最后添加它。有没有办法做到这一点。
  • 有几种方法但是我的方法是,为每个对象添加一个 id 键,然后使用 .sort() 方法所以如果你推送一个新对象,它将在数组中重新排序
  • 听起来可以,非常感谢大卫
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-06-16
  • 2015-07-04
  • 2022-10-14
  • 2019-03-27
  • 2011-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多