【问题标题】:Array.map / Filter a contigous array and then re-order it to be contiguous againArray.map / 过滤一个连续的数组,然后将其重新排序为连续的
【发布时间】:2021-01-13 00:08:05
【问题描述】:

使用 React,我有一个列表组件,它使用 array.map 来呈现项目列表。

列表项五花八门;每个其他列表项都有不同的背景颜色,这取决于提供列表项的数据结构的 id 字段是偶数还是奇数:

  ...

const useStyles = makeStyles((theme) => ({
  even: {
    backgroundColor: theme.palette.background.paper,
  },
  odd: {
    backgroundColor: "#c8c9c7",
  },
}));

...

const classes = useStyles();

...

{!list || list.length < 1 ? (
    <p>You have no assets selected...</p>
  ) : (
    list.map((items) => (
      <ListItem
        className={items.id % 2 === 0 ? classes.even : classes.odd}
        key={items.id}
      >
    ...
      />
    </ListItem>
  ))
)}

这是它使用的数据结构的示例:

{
    {
        "id":0,
        "foo":"This is a bar"
    },
    {
        "id":1,
        "foo":"This is also a bar"
    },
    {
        "id":2,
        "foo":"Yes, this too, is a bar"
    }
}

我需要删除项目。正常的 javascript.filter 会按预期生成不连续的 id:

{
    {
        "id":0,
        "foo":"This is a bar"
    },
    {
        "id":2,
        "foo":"Yes, this too, is a bar"
    }
}

我需要它们是连续的:

{
    {
        "id":0,
        "foo":"This is a bar"
    },
    {
        "id":1,
        "foo":"Yes, this too, is a bar"
    }
}

我有一个功能可以满足我的需要,但需要一些调整:

  const handleRemoveAsset = (id) => {
    const arrayCopy = [...assetListItems];
     const filteredArray = arrayCopy
       .filter((item) => item.id !== id)

     for (var i=0; i < filteredArray.length; i++) {
       filteredArray[i].id = i;
     }

    setAssetListItems(filteredArray);
  };

这可行,但不是简单地使用 React 进行 for 循环...我希望在整个过程中使用过滤器和/或映射,而不是使用我拥有的 for 循环。

我读到您可以链接过滤器和映射并尝试过,但无法完全解决。我想出了这个:

   const filteredArray = array
      .filter((item) => item.id !== id)
      .map((item, index) => {
           item && item.id ? item.id : index)});

... 编译失败 - 预期分配给函数调用,而是在 .map 之后的行上看到一个表达式

在这一点上的任何建议将不胜感激,谢谢!

【问题讨论】:

  • 在我看来,应该更新着色代码以使用索引而不是 id。
  • 你也可以使用 CSS:stackoverflow.com/questions/3084261/…
  • 感谢您的回复!我的 CSS 是垃圾,但使用这种方法似乎比通过 react 构建动态 CSS 样式要简单得多。我会探索它!

标签: javascript reactjs material-ui array.prototype.map


【解决方案1】:

您可以链接 mapfilter 并从 map 返回新对象,它会更新预先存在的 id。

[...assetListItems]
    .filter(item => item.id !== id)
    .map((item, index) => ({
      ...item,
      id: index,
    }));

【讨论】:

  • 感谢您提供此示例,这很有效,我将研究它以更好地理解地图和过滤器...您太棒了,感谢您的快速帮助!
【解决方案2】:

我刚刚考虑了另一种情况,如果id 不是以0 开头。如果您希望resultant array 中的起始id 成为第一个对象的id,那么这只是实现预期输出的另一种方式。

let data = [{id:0, foo:'This is a bar'},{id:1, foo:'This is also a bar'},{id:2, foo:'Yes, this too, is a bar'}];


const filterItems = (items, id) => {
  let lastPushedId = items[0]?.id;
  return items.filter(item => item.id !== id).map(item => ({
    ...item,
    id: lastPushedId++
  }))
}
console.log(filterItems(data, 1));

//`id` of the first object is `3`
data = [{id:3, foo:'This is a bar'},{id:4, foo:'This is also a bar'},{id:5, foo:'Yes, this too, is a bar'}];
console.log(filterItems(data, 3));
.as-console-wrapper {
  max-height: 100% !important;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-11
    • 1970-01-01
    • 2017-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多