Array.map /过滤一个连续的数组,然后重新排序使其再次连续

Array.map / Filter a contigous array and then re-order it to be contiguous again

使用 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 循环...我希望使用 filter and/or map 来完成这一切,而不是使用我拥有的 for 循环。

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

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

... 无法编译 - 预期对函数调用的赋值,而是在 .map.

之后的行上看到表达式

如有任何建议,我们将不胜感激,谢谢!

您可以链接 mapfilter 以及 return 来自 map 的新对象,它会更新 pre-existing id。

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

我刚刚考虑了另一种情况,如果 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;
}