Javascript 如何筛选同一属性中的对象数组?
我有一个产品选项“颜色、大小等”,正如我们所知,用户可以从选项“仅从颜色中选择红色”中选择一项,在这次我将所选的一项添加到单独的数组“所有选项用户选择”,但问题是用户可以在同一个字段中添加重复选项“例如颜色”,那么我如何解决这个问题? 最后一件事应该是:从单独的选项中选择一件 比如说Javascript 如何筛选同一属性中的对象数组?,javascript,reactjs,typescript,react-native,Javascript,Reactjs,Typescript,React Native,我有一个产品选项“颜色、大小等”,正如我们所知,用户可以从选项“仅从颜色中选择红色”中选择一项,在这次我将所选的一项添加到单独的数组“所有选项用户选择”,但问题是用户可以在同一个字段中添加重复选项“例如颜色”,那么我如何解决这个问题? 最后一件事应该是:从单独的选项中选择一件 比如说 SelectedOptions = [ { name:"red",id:88,optionType:"Color"}, { name:"XL
SelectedOptions = [
{ name:"red",id:88,optionType:"Color"},
{ name:"XL",id:22,optionType:"Size"},
....
]
但我现在要做的是什么
SelectedOptions = [
{ name:"red",id:88,optionType:"Color"},
{ name:"green",id:87,optionType:"Color"},
{ name:"XL",id:22,optionType:"Size"},
{ name:"M",id:22,optionType:"Size"},
....
];
我知道这是因为我将任何选定的一个推送到SelectedOptions数组,
我试图通过检查选项type
来解决这个问题,但我没有得到任何好主意
代码片段
const [selectedIndexColor, setSelectedIndexColor] = useState<
number | undefined
>();
const [selectedIndexText, setSelectedIndexText] = useState<number | null>();
const [selectedIndexImage, setSelectedIndexImage] = useState<number | null>();
interface ManipulateValueOptionProp extends valueOptionProp {
optionType: string;
}
const [allOptions, setAllOptions] = useState<ManipulateValueOptionProp[]>([]);
const renderValue = (value: valueOptionProp, type: string) => {
const selectedColor = selectedIndexColor === value.id;
const selectedText = selectedIndexText === value.id;
const selectedImage = selectedIndexImage === value.id;
switch (type) {
case 'text': {
return (
<View
style={[
styles.selectedText,
{backgroundColor: selectedText ? 'black' : 'transparent'},
]}>
<Text
style={{
textAlign: 'center',
color: selectedText ? 'white' : 'black',
fontSize: 12,
}}>
{value.name_en}
</Text>
</View>
);
}
case 'Color': {
return (
<>
<View
// @ts-ignore
// eslint-disable-next-line react-native/no-inline-styles
style={{
width: 53,
height: 53,
backgroundColor: value.display_value,
}}
/>
{selectedColor ? (
<View style={styles.selectedColor}>
<CheckmarkIcon color="black" />
</View>
) : null}
</>
);
}
case 'images': {
return (
<>
<Image
// @ts-ignore
source={{uri: value.display_value}}
// eslint-disable-next-line react-native/no-inline-styles
style={{width: 53, height: 53, backgroundColor: '#0f4c7f'}}
/>
{selectedImage ? (
<View style={styles.selectedColor}>
<CheckmarkIcon />
</View>
) : null}
</>
);
}
default: {
return null;
}
}
};
{item.options.map((option) => {
return (
<View style={styles.optionsBox}>
<Text style={styles.optionTxt}>{option.label_en}</Text>
<View style={{flexDirection: 'row'}}>
{option.values.map((value: valueOptionProp) => {
return (
<ScalePressable
key={`${option.id}${value.id}`}
onPress={() => {
option.type === 'Color' &&
setSelectedIndexColor(value.id);
option.type === 'text' && setSelectedIndexText(value.id);
option.type === 'images' &&
setSelectedIndexImage(value.id);
if (
!allOptions.some(
(alreadyExist) => alreadyExist.id === value.id,
)
) {
setAllOptions((options) => [
...options,
{...value, optionType: option.type},
]);
}
}}>
<View style={styles.values}>
{renderValue(value, option.type)}
</View>
</ScalePressable>
);
})}
</View>
</View>
);
})}
const[selectedIndexColor,setSelectedIndexColor]=useState<
编号|未定义
>();
常量[selectedIndexText,setSelectedIndexText]=useState();
常量[selectedIndexImage,setSelectedIndexImage]=useState();
接口操作valueOptionProp扩展了valueOptionProp{
optionType:字符串;
}
常量[allOptions,setAllOptions]=useState([]);
常量renderValue=(值:valueOptionProp,类型:string)=>{
const selectedColor=selectedIndexColor==value.id;
常量selectedText=selectedIndexText==value.id;
const selectedImage=selectedIndexImage==value.id;
开关(类型){
案例“文本”:{
返回(
{value.name_en}
);
}
案例“颜色”:{
返回(
{selectedColor(
):null}
);
}
案例“图像”:{
返回(
{选择图像(
):null}
);
}
默认值:{
返回null;
}
}
};
{item.options.map((option)=>{
返回(
{option.label_en}
{option.values.map((值:valueOptionProp)=>{
返回(
{
option.type==“颜色”&&
setSelectedIndexColor(value.id);
option.type=='text'&&setSelectedIndexText(value.id);
option.type==“图像”&&
设置SelectedIndexImage(value.id);
如果(
!所有选项。一些(
(alreadyExist)=>alreadyExist.id==value.id,
)
) {
setAllOptions((选项)=>[
…选项,
{…值,optionType:option.type},
]);
}
}}>
{renderValue(值,option.type)}
);
})}
);
})}
这里有一个可能的解决方案。您可以考虑通过使用与新选项相同的选项类型移除所有选项来创建新数组,然后将新选项添加到新数组中。
let selectedOptions = [
{ name: 'red', id: 88, optionType: 'Color' },
{ name: 'XL', id: 22, optionType: 'Size' },
];
let newOption = { name: 'green', id: 87, optionType: 'Color' };
selectedOptions = [
...selectedOptions.filter(
option => option.optionType != newOption.optionType
),
newOption,
];
在我看来,当用户按下相同的过滤器选项时,您只需要从
allOptions
数组中删除取消选择的选项
onPress={() => {
option.type === 'Color' && setSelectedIndexColor(value.id);
option.type === 'text' && setSelectedIndexText(value.id);
option.type === 'images' && setSelectedIndexImage(value.id);
if (allOptions.some(option => option.type === value.type)) {
setAllOptions(options => options.filter(option => option.type !== value.type));
} else {
setAllOptions((options) => [
...options,
{ ...value, optionType: option.type },
]);
}
}}
你的问题很难理解。你到底想过滤什么?选择的选项是什么?基于所选选项的数据?您是否还可以包含一些示例输入的预期结果?@drewrese情况是,我得到了三种类型的选项“颜色、图像、文本”作为对象数组,我呈现了选项名称及其值,正如您在屏幕截图中看到的,当用户选择任何选项“红色”时,我将此选项推送到用户选择的所有选项,所以问题是当用户选择红色,然后取消它,并选择绿色的引擎盖下我存储红色之前,所以我会得到两个选项在同一类型的“颜色”,我想要的只是选择用户选择的最后一件事!我希望你能很好地理解我,如果你查看输出代码,你就会理解我的问题。基本上,你需要实现删除用户“取消选择”的选项?嗯,所以我们首先分散所有选项,并使用
过滤器
删除重复的类型,然后添加新选项?为什么我们要创建一个新数组?我有点困惑:\n这里使用filter
会删除optionType
与newOption
相同的所有元素。然后应用扩展运算符从应用filter
的结果访问元素,并且newOption
包含在数组文本中。选择不执行就地操作(即,推送
)是为了更符合函数式编程方法,这增加了代码库的健壮性。遗憾的是,它没有按预期工作,它仍然存储我以前选择的未选择的数据,顺便说一句,上面的答案非常有效,请看一看!,当然谢谢你抽出时间真的appreciate@OliverD你确定你正确地实现了它吗?这是从状态数组中删除元素的标准模式。上述解决方案不必要地在数据上循环两次,只是为了删除一个选项(仅供参考),一次是为了删除匹配的“类型”,第二次是为了复制到新数组。@OliverD啊,我现在明白你的意思了。我只是扩展了检查选项id的逻辑,但是逻辑应该是查看过滤器选项类型。请再查一下。这实际上是两种解决方案之间的冲突,两种方法都将数据迭代两次。唯一改进的方法是将筛选选项存储在地图/对象/字典中,这样您可以获得O(1)
查找,而不是O(n)
。是的,我确定!在过滤器中有一个语法问题
我修正了它:D请检查这个记录