我如何获取一个对象数组并减少它,以便组合重复对象键的数据?
How do I take an array of objects and reduce it so that data at a repeated object key is combined?
我正在开发一个模仿零售网站的 React 应用程序。我的主页显示一个项目,下面有相关产品的卡片组件。当我单击其中一个相关产品上的按钮时,我会打开一个比较模式,比较当前产品和所点击产品的功能。我认为要实现这一点,我将创建一个包含被点击产品和主页产品的组合功能的数组。我一直在努力创建一个对象数组,其中每个独特的功能都有一个对象,其中包含有关功能以及该功能属于哪个产品的数据。
截至目前,我已经能够获得两个产品具有的所有功能的数组,但如果产品具有重叠的功能,则该数组会重复。这让我不确定如何呈现比较 table,因为我计划映射数组并为每个特征创建一个 table 行。我当前格式化这些功能的代码如下:
formatFeatures: (currentProd, clickedProd) => {
let combinedFeatures = [];
if (clickedProd.features) {
clickedProd.features.forEach(feature => {
let obj = {}
let vals = Object.values(feature);
obj[vals[0]] = [vals[1], clickedProd.id]
combinedFeatures.push(obj)
})
}
currentProd.features.forEach(feature => {
let obj = {}
let vals = Object.values(feature);
obj[vals[0]] = [vals[1], currentProd.id]
combinedFeatures.push(obj)
})
let formattedFeatures = combinedFeatures.reduce((allFeatures, feature) => {
if (Object.keys(feature) in allFeatures) {
allFeatures = [allFeatures[Object.keys(feature)]].concat(feature);
} else {
allFeatures.push(feature);
}
return allFeatures;
}, [])
结果是:
[{
"Fabric": ["100% Cotton", 28214]
}, {
"Cut": ["Skinny", 28214]
}, {
"Fabric": ["Canvas", 28212]
}, {
"Buttons": ["Brass", 28212]
}]
这与我正在寻找的非常接近,我有一个对象数组,其中包含有关产品的功能和产品 ID 的信息,但“Fabric”中的重复是我正在努力的事情整理。理想情况下,结果应如下所示:
[{
"Fabric": ["100% Cotton", 28214],
["Canvas", 28212]
}, {
"Cut": ["Skinny", 28214]
}, {
"Buttons": ["Brass", 28212]
}]
如果有人可以帮助指导我如何更改我的格式化功能来完成此操作,我将不胜感激。或者,如果有人知道根据我当前的结果动态格式化 table 每个独特功能的单行,那也很棒。
进入我的辅助函数的数据如下:
当前产品:
{
"id": 28212,
"name": "Camo Onesie",
"slogan": "Blend in to your crowd",
"description": "The So Fatigues will wake you up and fit you in. This high energy camo will have you blending in to even the wildest surroundings.",
"category": "Jackets",
"default_price": "140.00",
"created_at": "2021-07-10T17:00:03.509Z",
"updated_at": "2021-07-10T17:00:03.509Z",
"features": [{
"feature": "Fabric",
"value": "Canvas"
}, {
"feature": "Buttons",
"value": "Brass"
}]
}
点击量:
{
"name": "Morning Joggers",
"category": "Pants",
"originalPrice": "40.00",
"salePrice": null,
"photo": "https://images.unsplash.com/photo-1552902865-b72c031ac5ea?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=300&q=80",
"id": 28214,
"features": [{
"feature": "Fabric",
"value": "100% Cotton"
}, {
"feature": "Cut",
"value": "Skinny"
}]
}
似乎有一个更大的问题是如何构建数据。你说理想情况下你的结果应该是这样的:
[
{
"Fabric":
["100% Cotton",28214],
["Canvas",28212]
},
{
"Cut":
["Skinny",28214]
},
{
"Buttons":
["Brass",28212]
}
]
但您真正想从中得到的是每个项目特征(如果存在)的行和关联值的组合列表。然后,您真正需要的只是要显示的每一行的键数组,以及允许您通过该键访问所需 属性 的对象。
键数组可能如下所示:
["Fabric", "Cut", "Buttons"]
您想要使用这些键访问属性的对象,例如您的 CurrentProd
,可能是这个(请注意,您可以通过调用 CurrentProd.features["FeatureName"]
访问功能):
{
"id":28212,
"name":"Camo Onesie",
// ... //
"features": {
"Fabric": "Canvas",
"Buttons": "Brass"
}
}
话虽如此,要获得这些东西,您可以通过减少 CurrentProd.features
和 ClickedProd.features
的组合数组来获得我们称之为 allFeatureKeys
的键数组:
const allFeatureKeys = [
...CurrentProd.features,
...ClickedProd.features
].reduce((acc, cur) => {
return acc.findIndex(cur.feature) > -1 ? [...acc, cur.feature] : acc
},
[]
);
并且您可以通过减少其特征数组将 CurrentProd 修改为上述数据形状,我们称其为 modifiedCurrentProd
:
const modifiedCurrentProd = {
...CurrentProd,
features: CurrentProd.features.reduce((acc, cur) => {
return {...acc, [cur.feature]: cur.value}
}, {})
}
对 modifiedClickedProd
对象重复该操作,然后在创建 table 值时,CurrentProd.features 和 ClickedProd.features 值可用于查找。
仅作为示例,因为我不知道你的反应结构或你想显示什么数据,你可以渲染 table 行中的值映射到键上以构成每一行,对于每个功能键,您可以从 modifiedCurrentProd
或 modifiedClickedProd
对象的功能 属性:
中访问值
<div id="table">
{allFeatureKeys.map((featureKey) => {
return <div id="table-row">
<div>{featureKey}</div>
<div>
{
modifiedCurrentProd.features[featureKey] !== undefined
? modifiedCurrentProd.id
: "n/a"
}
</div>
<div>
{
modifiedClickedProd.features[featureKey] !== undefined
? modifiedClickedProd.id
: "n/a"
}
</div>
</div>
})}
</div>
首先目标数据结构需要是fixed/optimized。看起来 OP 确实专注于基于通用 Feature
的东西(比如 Fabric, Cut, Buttons) 而这些特征值似乎与 Product
。因此,对于同一个 feature,值对于 product feature 是唯一的。为了不丢失产品信息,目标格式的 feature item 需要反映其相关产品的 id
属性 .
可行且仍然足够灵活的目标数据结构可能如下所示...
{
"Fabric": [{
productId: 28214,
value: "100% Cotton",
}, {
productId: 28212,
value: "Canvas",
}],
"Cut": [{
productId: 28214,
value: "Skinny",
}],
"Buttons": [{
productId: 28212,
value: "Brass",
}],
}
任何方法都应从 product
的 features
列表的数据规范化映射过程开始,其中每个 特征项 将分配其 product
相关的 id
。
因此 功能项 像 { feature: "Buttons", value: "Brass" }
被临时映射到 { productId: 28212, feature: "Buttons", value: "Brass" }
.
两个规范化的数据项列表现在可以连接起来,最终 processed/reduced 成为最终的目标结构 ...
function mergeBoundProductId(item) {
return { ...this, ...item };
}
function aggregateProductFeatureValueLists(index, productFeature) {
const { feature, ...featureValue } = productFeature;
const featureList = index[feature] ??= [];
//const featureList = index[feature] || (index[feature] = []);
featureList.push(featureValue);
return index;
}
function createIndexOfProductFeatureValues(clickedProd, currentProd) {
const { features:clickedFeatures } = clickedProd;
const { features:currentFeatures } = currentProd;
return [
...clickedFeatures.map(mergeBoundProductId, { productId: clickedProd.id }),
...currentFeatures.map(mergeBoundProductId, { productId: currentProd.id }),
].reduce(aggregateProductFeatureValueLists, {});
}
const currentProduct = {
id: 28212,
name: "Camo Onesie",
// ... more properties ...
features: [{
feature: "Fabric",
value: "Canvas",
}, {
feature: "Buttons",
value: "Brass",
}],
};
const clickedProduct = {
name: "Morning Joggers",
// ... more properties ...
id: 28214,
features: [{
feature: "Fabric",
value: "100% Cotton",
}, {
feature: "Cut",
value: "Skinny",
}],
};
console.log(
'createIndexOfProductFeatureValues(clickedProduct, currentProduct) ...',
createIndexOfProductFeatureValues(clickedProduct, currentProduct)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
将代码分解成专用进程的好处是更容易重构,例如改变了目标结构,比如更接近 OP 正在寻找的东西。
reducer 函数的变化很小。这只是两个变化,每个变化都在其行中几乎不可察觉...
function mergeBoundProductId(item) {
return { ...this, ...item };
}
function aggregateProductFeatureValueLists(index, productFeature) {
const { feature, productId, value } = productFeature;
const featureList = index[feature] ??= [];
featureList.push([value, productId]);
return index;
}
function createIndexOfProductFeatureValues(clickedProd, currentProd) {
const { features:clickedFeatures } = clickedProd;
const { features:currentFeatures } = currentProd;
return [
...clickedFeatures.map(mergeBoundProductId, { productId: clickedProd.id }),
...currentFeatures.map(mergeBoundProductId, { productId: currentProd.id }),
].reduce(aggregateProductFeatureValueLists, {});
}
console.log(
'createIndexOfProductFeatureValues(clickedProduct, currentProduct) ...',
createIndexOfProductFeatureValues(clickedProduct, currentProduct)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
<script>
const currentProduct = {
id: 28212,
name: "Camo Onesie",
// ... more properties ...
features: [{
feature: "Fabric",
value: "Canvas",
}, {
feature: "Buttons",
value: "Brass",
}],
};
const clickedProduct = {
name: "Morning Joggers",
// ... more properties ...
id: 28214,
features: [{
feature: "Fabric",
value: "100% Cotton",
}, {
feature: "Cut",
value: "Skinny",
}],
};
</script>
最后一个示例的目的也是为了证明易于重构代码库的优势。
这里的 main 函数从 createIndexOfProductFeatureValues
重命名为 createListOfProductFeatureValues
。
它的实现也有类似的变化,但只是在如何使用其初始值调用 reducer 函数的方式上。
reducer 函数也没有显着变化,只是在处理 accumulating/aggregating collector
对象的方式上有所变化。
结果是一个干净的基于数组的对象结构...
function mergeBoundProductId(item) {
return { ...this, ...item };
}
function aggregateProductFeatureValueLists(collector, productFeature) {
const { feature, productId, value } = productFeature;
const { index, list } = collector;
const featureItem = index[feature] ??= { feature, values: [] };
if (featureItem.values.length === 0) {
list.push(featureItem);
}
featureItem.values.push([value, productId]);
return collector;
}
function createListOfProductFeatureValues(clickedProd, currentProd) {
const { features:clickedFeatures } = clickedProd;
const { features:currentFeatures } = currentProd;
return [
...clickedFeatures.map(mergeBoundProductId, { productId: clickedProd.id }),
...currentFeatures.map(mergeBoundProductId, { productId: currentProd.id }),
].reduce(aggregateProductFeatureValueLists, { index: {}, list: [] }).list;
}
console.log(
'createListOfProductFeatureValues(clickedProduct, currentProduct) ...',
createListOfProductFeatureValues(clickedProduct, currentProduct)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
<script>
const currentProduct = {
id: 28212,
name: "Camo Onesie",
// ... more properties ...
features: [{
feature: "Fabric",
value: "Canvas",
}, {
feature: "Buttons",
value: "Brass",
}],
};
const clickedProduct = {
name: "Morning Joggers",
// ... more properties ...
id: 28214,
features: [{
feature: "Fabric",
value: "100% Cotton",
}, {
feature: "Cut",
value: "Skinny",
}],
};
</script>
您已经循环了一次。不减也能得到
const formatFeatures = (currentProd, clickedProd) => {
const formattedFeatures = {};
if (clickedProd.features) {
clickedProd.features.forEach(feature => {
const vals = Object.values(feature);
if (!formattedFeatures.hasOwnProperty(vals[0])) {
formattedFeatures[vals[0]] = [];
}
formattedFeatures[vals[0]].push([vals[1], clickedProd.id]);
});
}
currentProd.features.forEach(feature => {
const vals = Object.values(feature);
if (!formattedFeatures.hasOwnProperty(vals[0])) {
formattedFeatures[vals[0]] = [];
}
formattedFeatures[vals[0]].push([vals[1], currentProd.id]);
})
return formattedFeatures;
}
const currentProd = {
"id": 28212,
"name": "Camo Onesie",
"slogan": "Blend in to your crowd",
"description": "The So Fatigues will wake you up and fit you in. This high energy camo will have you blending in to even the wildest surroundings.",
"category": "Jackets",
"default_price": "140.00",
"created_at": "2021-07-10T17:00:03.509Z",
"updated_at": "2021-07-10T17:00:03.509Z",
"features": [{
"feature": "Fabric",
"value": "Canvas"
}, {
"feature": "Buttons",
"value": "Brass"
}]
};
const clickedProd = {
"name": "Morning Joggers",
"category": "Pants",
"originalPrice": "40.00",
"salePrice": null,
"photo": "https://images.unsplash.com/photo-1552902865-b72c031ac5ea?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=300&q=80",
"id": 28214,
"features": [{
"feature": "Fabric",
"value": "100% Cotton"
}, {
"feature": "Cut",
"value": "Skinny"
}]
};
console.log(formatFeatures(currentProd, clickedProd));
.as-console-wrapper { min-height: 100%!important; top: 0; }
我正在开发一个模仿零售网站的 React 应用程序。我的主页显示一个项目,下面有相关产品的卡片组件。当我单击其中一个相关产品上的按钮时,我会打开一个比较模式,比较当前产品和所点击产品的功能。我认为要实现这一点,我将创建一个包含被点击产品和主页产品的组合功能的数组。我一直在努力创建一个对象数组,其中每个独特的功能都有一个对象,其中包含有关功能以及该功能属于哪个产品的数据。
截至目前,我已经能够获得两个产品具有的所有功能的数组,但如果产品具有重叠的功能,则该数组会重复。这让我不确定如何呈现比较 table,因为我计划映射数组并为每个特征创建一个 table 行。我当前格式化这些功能的代码如下:
formatFeatures: (currentProd, clickedProd) => {
let combinedFeatures = [];
if (clickedProd.features) {
clickedProd.features.forEach(feature => {
let obj = {}
let vals = Object.values(feature);
obj[vals[0]] = [vals[1], clickedProd.id]
combinedFeatures.push(obj)
})
}
currentProd.features.forEach(feature => {
let obj = {}
let vals = Object.values(feature);
obj[vals[0]] = [vals[1], currentProd.id]
combinedFeatures.push(obj)
})
let formattedFeatures = combinedFeatures.reduce((allFeatures, feature) => {
if (Object.keys(feature) in allFeatures) {
allFeatures = [allFeatures[Object.keys(feature)]].concat(feature);
} else {
allFeatures.push(feature);
}
return allFeatures;
}, [])
结果是:
[{
"Fabric": ["100% Cotton", 28214]
}, {
"Cut": ["Skinny", 28214]
}, {
"Fabric": ["Canvas", 28212]
}, {
"Buttons": ["Brass", 28212]
}]
这与我正在寻找的非常接近,我有一个对象数组,其中包含有关产品的功能和产品 ID 的信息,但“Fabric”中的重复是我正在努力的事情整理。理想情况下,结果应如下所示:
[{
"Fabric": ["100% Cotton", 28214],
["Canvas", 28212]
}, {
"Cut": ["Skinny", 28214]
}, {
"Buttons": ["Brass", 28212]
}]
如果有人可以帮助指导我如何更改我的格式化功能来完成此操作,我将不胜感激。或者,如果有人知道根据我当前的结果动态格式化 table 每个独特功能的单行,那也很棒。
进入我的辅助函数的数据如下:
当前产品:
{
"id": 28212,
"name": "Camo Onesie",
"slogan": "Blend in to your crowd",
"description": "The So Fatigues will wake you up and fit you in. This high energy camo will have you blending in to even the wildest surroundings.",
"category": "Jackets",
"default_price": "140.00",
"created_at": "2021-07-10T17:00:03.509Z",
"updated_at": "2021-07-10T17:00:03.509Z",
"features": [{
"feature": "Fabric",
"value": "Canvas"
}, {
"feature": "Buttons",
"value": "Brass"
}]
}
点击量:
{
"name": "Morning Joggers",
"category": "Pants",
"originalPrice": "40.00",
"salePrice": null,
"photo": "https://images.unsplash.com/photo-1552902865-b72c031ac5ea?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=300&q=80",
"id": 28214,
"features": [{
"feature": "Fabric",
"value": "100% Cotton"
}, {
"feature": "Cut",
"value": "Skinny"
}]
}
似乎有一个更大的问题是如何构建数据。你说理想情况下你的结果应该是这样的:
[
{
"Fabric":
["100% Cotton",28214],
["Canvas",28212]
},
{
"Cut":
["Skinny",28214]
},
{
"Buttons":
["Brass",28212]
}
]
但您真正想从中得到的是每个项目特征(如果存在)的行和关联值的组合列表。然后,您真正需要的只是要显示的每一行的键数组,以及允许您通过该键访问所需 属性 的对象。
键数组可能如下所示:
["Fabric", "Cut", "Buttons"]
您想要使用这些键访问属性的对象,例如您的 CurrentProd
,可能是这个(请注意,您可以通过调用 CurrentProd.features["FeatureName"]
访问功能):
{
"id":28212,
"name":"Camo Onesie",
// ... //
"features": {
"Fabric": "Canvas",
"Buttons": "Brass"
}
}
话虽如此,要获得这些东西,您可以通过减少 CurrentProd.features
和 ClickedProd.features
的组合数组来获得我们称之为 allFeatureKeys
的键数组:
const allFeatureKeys = [
...CurrentProd.features,
...ClickedProd.features
].reduce((acc, cur) => {
return acc.findIndex(cur.feature) > -1 ? [...acc, cur.feature] : acc
},
[]
);
并且您可以通过减少其特征数组将 CurrentProd 修改为上述数据形状,我们称其为 modifiedCurrentProd
:
const modifiedCurrentProd = {
...CurrentProd,
features: CurrentProd.features.reduce((acc, cur) => {
return {...acc, [cur.feature]: cur.value}
}, {})
}
对 modifiedClickedProd
对象重复该操作,然后在创建 table 值时,CurrentProd.features 和 ClickedProd.features 值可用于查找。
仅作为示例,因为我不知道你的反应结构或你想显示什么数据,你可以渲染 table 行中的值映射到键上以构成每一行,对于每个功能键,您可以从 modifiedCurrentProd
或 modifiedClickedProd
对象的功能 属性:
<div id="table">
{allFeatureKeys.map((featureKey) => {
return <div id="table-row">
<div>{featureKey}</div>
<div>
{
modifiedCurrentProd.features[featureKey] !== undefined
? modifiedCurrentProd.id
: "n/a"
}
</div>
<div>
{
modifiedClickedProd.features[featureKey] !== undefined
? modifiedClickedProd.id
: "n/a"
}
</div>
</div>
})}
</div>
首先目标数据结构需要是fixed/optimized。看起来 OP 确实专注于基于通用 Feature
的东西(比如 Fabric, Cut, Buttons) 而这些特征值似乎与 Product
。因此,对于同一个 feature,值对于 product feature 是唯一的。为了不丢失产品信息,目标格式的 feature item 需要反映其相关产品的 id
属性 .
可行且仍然足够灵活的目标数据结构可能如下所示...
{
"Fabric": [{
productId: 28214,
value: "100% Cotton",
}, {
productId: 28212,
value: "Canvas",
}],
"Cut": [{
productId: 28214,
value: "Skinny",
}],
"Buttons": [{
productId: 28212,
value: "Brass",
}],
}
任何方法都应从 product
的 features
列表的数据规范化映射过程开始,其中每个 特征项 将分配其 product
相关的 id
。
因此 功能项 像 { feature: "Buttons", value: "Brass" }
被临时映射到 { productId: 28212, feature: "Buttons", value: "Brass" }
.
两个规范化的数据项列表现在可以连接起来,最终 processed/reduced 成为最终的目标结构 ...
function mergeBoundProductId(item) {
return { ...this, ...item };
}
function aggregateProductFeatureValueLists(index, productFeature) {
const { feature, ...featureValue } = productFeature;
const featureList = index[feature] ??= [];
//const featureList = index[feature] || (index[feature] = []);
featureList.push(featureValue);
return index;
}
function createIndexOfProductFeatureValues(clickedProd, currentProd) {
const { features:clickedFeatures } = clickedProd;
const { features:currentFeatures } = currentProd;
return [
...clickedFeatures.map(mergeBoundProductId, { productId: clickedProd.id }),
...currentFeatures.map(mergeBoundProductId, { productId: currentProd.id }),
].reduce(aggregateProductFeatureValueLists, {});
}
const currentProduct = {
id: 28212,
name: "Camo Onesie",
// ... more properties ...
features: [{
feature: "Fabric",
value: "Canvas",
}, {
feature: "Buttons",
value: "Brass",
}],
};
const clickedProduct = {
name: "Morning Joggers",
// ... more properties ...
id: 28214,
features: [{
feature: "Fabric",
value: "100% Cotton",
}, {
feature: "Cut",
value: "Skinny",
}],
};
console.log(
'createIndexOfProductFeatureValues(clickedProduct, currentProduct) ...',
createIndexOfProductFeatureValues(clickedProduct, currentProduct)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
将代码分解成专用进程的好处是更容易重构,例如改变了目标结构,比如更接近 OP 正在寻找的东西。
reducer 函数的变化很小。这只是两个变化,每个变化都在其行中几乎不可察觉...
function mergeBoundProductId(item) {
return { ...this, ...item };
}
function aggregateProductFeatureValueLists(index, productFeature) {
const { feature, productId, value } = productFeature;
const featureList = index[feature] ??= [];
featureList.push([value, productId]);
return index;
}
function createIndexOfProductFeatureValues(clickedProd, currentProd) {
const { features:clickedFeatures } = clickedProd;
const { features:currentFeatures } = currentProd;
return [
...clickedFeatures.map(mergeBoundProductId, { productId: clickedProd.id }),
...currentFeatures.map(mergeBoundProductId, { productId: currentProd.id }),
].reduce(aggregateProductFeatureValueLists, {});
}
console.log(
'createIndexOfProductFeatureValues(clickedProduct, currentProduct) ...',
createIndexOfProductFeatureValues(clickedProduct, currentProduct)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
<script>
const currentProduct = {
id: 28212,
name: "Camo Onesie",
// ... more properties ...
features: [{
feature: "Fabric",
value: "Canvas",
}, {
feature: "Buttons",
value: "Brass",
}],
};
const clickedProduct = {
name: "Morning Joggers",
// ... more properties ...
id: 28214,
features: [{
feature: "Fabric",
value: "100% Cotton",
}, {
feature: "Cut",
value: "Skinny",
}],
};
</script>
最后一个示例的目的也是为了证明易于重构代码库的优势。
这里的 main 函数从 createIndexOfProductFeatureValues
重命名为 createListOfProductFeatureValues
。
它的实现也有类似的变化,但只是在如何使用其初始值调用 reducer 函数的方式上。
reducer 函数也没有显着变化,只是在处理 accumulating/aggregating collector
对象的方式上有所变化。
结果是一个干净的基于数组的对象结构...
function mergeBoundProductId(item) {
return { ...this, ...item };
}
function aggregateProductFeatureValueLists(collector, productFeature) {
const { feature, productId, value } = productFeature;
const { index, list } = collector;
const featureItem = index[feature] ??= { feature, values: [] };
if (featureItem.values.length === 0) {
list.push(featureItem);
}
featureItem.values.push([value, productId]);
return collector;
}
function createListOfProductFeatureValues(clickedProd, currentProd) {
const { features:clickedFeatures } = clickedProd;
const { features:currentFeatures } = currentProd;
return [
...clickedFeatures.map(mergeBoundProductId, { productId: clickedProd.id }),
...currentFeatures.map(mergeBoundProductId, { productId: currentProd.id }),
].reduce(aggregateProductFeatureValueLists, { index: {}, list: [] }).list;
}
console.log(
'createListOfProductFeatureValues(clickedProduct, currentProduct) ...',
createListOfProductFeatureValues(clickedProduct, currentProduct)
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
<script>
const currentProduct = {
id: 28212,
name: "Camo Onesie",
// ... more properties ...
features: [{
feature: "Fabric",
value: "Canvas",
}, {
feature: "Buttons",
value: "Brass",
}],
};
const clickedProduct = {
name: "Morning Joggers",
// ... more properties ...
id: 28214,
features: [{
feature: "Fabric",
value: "100% Cotton",
}, {
feature: "Cut",
value: "Skinny",
}],
};
</script>
您已经循环了一次。不减也能得到
const formatFeatures = (currentProd, clickedProd) => {
const formattedFeatures = {};
if (clickedProd.features) {
clickedProd.features.forEach(feature => {
const vals = Object.values(feature);
if (!formattedFeatures.hasOwnProperty(vals[0])) {
formattedFeatures[vals[0]] = [];
}
formattedFeatures[vals[0]].push([vals[1], clickedProd.id]);
});
}
currentProd.features.forEach(feature => {
const vals = Object.values(feature);
if (!formattedFeatures.hasOwnProperty(vals[0])) {
formattedFeatures[vals[0]] = [];
}
formattedFeatures[vals[0]].push([vals[1], currentProd.id]);
})
return formattedFeatures;
}
const currentProd = {
"id": 28212,
"name": "Camo Onesie",
"slogan": "Blend in to your crowd",
"description": "The So Fatigues will wake you up and fit you in. This high energy camo will have you blending in to even the wildest surroundings.",
"category": "Jackets",
"default_price": "140.00",
"created_at": "2021-07-10T17:00:03.509Z",
"updated_at": "2021-07-10T17:00:03.509Z",
"features": [{
"feature": "Fabric",
"value": "Canvas"
}, {
"feature": "Buttons",
"value": "Brass"
}]
};
const clickedProd = {
"name": "Morning Joggers",
"category": "Pants",
"originalPrice": "40.00",
"salePrice": null,
"photo": "https://images.unsplash.com/photo-1552902865-b72c031ac5ea?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=300&q=80",
"id": 28214,
"features": [{
"feature": "Fabric",
"value": "100% Cotton"
}, {
"feature": "Cut",
"value": "Skinny"
}]
};
console.log(formatFeatures(currentProd, clickedProd));
.as-console-wrapper { min-height: 100%!important; top: 0; }