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.
之后的行上看到表达式
如有任何建议,我们将不胜感激,谢谢!
您可以链接 map
和 filter
以及 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;
}
使用 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.
之后的行上看到表达式如有任何建议,我们将不胜感激,谢谢!
您可以链接 map
和 filter
以及 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;
}