如何使用数组值重构 reduce
How to refactor reduce with array value
我正在尝试清理代码。
selectedGroup.items
看起来像这样(简化):
[
{ szenarien: [{extent: {xmin: 1, xmax: 2, ymin: 3, ymax: 4}}, ...] },
{ extent: {...}] } // Extent has same properties as above
]
下面是我的映射代码。目标:获取多边形集合的最外层点
const coordinateValues = selectedGroup.items.reduce(
//TODO: Make this a bit more readable
(acc, item) => {
// item is a group
if (item.szenarios) {
item.szenarios.map((szenario) => {
acc.xmin.push(szenario.extent.xmin);
acc.xmax.push(szenario.extent.xmax);
acc.ymin.push(szenario.extent.ymin);
acc.ymax.push(szenario.extent.ymax);
});
}
// item is a szenario
else {
acc.xmin.push(item.extent.xmin);
acc.xmax.push(item.extent.xmax);
acc.ymin.push(item.extent.ymin);
acc.ymax.push(item.extent.ymax);
}
return acc;
},
{ xmin: [], xmax: [], ymin: [], ymax: [] }
);
// Prepare an extent with the smallest xmin, ymin and the biggest xmax, ymax to have all szenarios in it
const calculatedGroupExtent: __esri.Extent = new EsriExtent({
xmax: Math.max(...coordinateValues.xmax) + 200,
xmin: Math.min(...coordinateValues.xmin) - 200,
ymax: Math.max(...coordinateValues.ymax) + 200,
ymin: Math.min(...coordinateValues.ymin) - 200,
spatialReference: { wkid: 2056 },
});
显然它不是真正可读的。如果不添加许多 "readability constants"(因此没有任何改进)
,我找不到一个漂亮的方法来简化它
您可以制作一个辅助函数,它接受一个 szenario
对象并将每个 ['xmin', 'xmax', 'ymin', 'ymax']
属性推送到适当的数组。然后,在迭代项目时,您只需要测试项目是否是一个组(在这种情况下您会做 item.szenarios.forEach(addSzenario)
),否则添加单个 szenario:addSzenario(item.extent)
const props = ['xmin', 'xmax', 'ymin', 'ymax'];
const coordinateValues = Object.fromEntries(
props.map(prop => [prop, []])
);
const addSzenario = (szenario) => {
for (const prop of props) {
coordinateValues[prop].push(szenario[prop]);
}
};
for (const item of selectedGroup.items) {
// item is a group
if (item.szenarios) {
item.szenarios.forEach(addSzenario);
} else {
addSzenario(item.extent);
}
}
您可以使用 reduce 来计算最大值和最小值。
const getVal = (item) => {
return item.szenarios ? szenario.extent[key] : item.extent[key];
}
const getMin = (group, key) => {
return group.items.reduce((acc, item) => {
return Math.min(acc, getVal(item));
}, Number.MAX_SAFE_INTEGER);
}
const getMax = (group, key) => {
return group.items.reduce((acc, item) => {
return Math.max(acc, getVal(item));
}, Number.MIN_SAFE_INTEGER);
}
const xmin = getMin(selectedGroup, "xmin");
const xmax = getMin(selectedGroup, "xmax");
const ymin = getMin(selectedGroup, "ymin");
const ymax = getMin(selectedGroup, "ymax");
我想出了两个答案的混合:
const pointIdentifiers = ['xmin', 'xmax', 'ymin', 'ymax'];
// Get all coordinates of the group's szenarios
const coordinateValues = selectedGroup.items.reduce((acc, item) => {
// Differenciate if item is a szenario itself or a group (with szenarios)
const szenarios = item.szenarios ? item.szenarios : [item];
// Add every point for every szenario
szenarios.forEach((valueItem) => {
pointIdentifiers.forEach((identifier) => {
acc[identifier].push(valueItem.extent[identifier]);
});
});
return acc;
}, Object.fromEntries(pointIdentifiers.map((prop) => [prop, []])));
// Prepare an extent with the smallest xmin, ymin and the biggest xmax, ymax to have all szenarios in it
const calculatedGroupExtent: __esri.Extent = new EsriExtent({
xmax: Math.max(...coordinateValues.xmax) + 200,
xmin: Math.min(...coordinateValues.xmin) - 200,
ymax: Math.max(...coordinateValues.ymax) + 200,
ymin: Math.min(...coordinateValues.ymin) - 200,
spatialReference: { wkid: 2056 },
});
我正在尝试清理代码。
selectedGroup.items
看起来像这样(简化):
[
{ szenarien: [{extent: {xmin: 1, xmax: 2, ymin: 3, ymax: 4}}, ...] },
{ extent: {...}] } // Extent has same properties as above
]
下面是我的映射代码。目标:获取多边形集合的最外层点
const coordinateValues = selectedGroup.items.reduce(
//TODO: Make this a bit more readable
(acc, item) => {
// item is a group
if (item.szenarios) {
item.szenarios.map((szenario) => {
acc.xmin.push(szenario.extent.xmin);
acc.xmax.push(szenario.extent.xmax);
acc.ymin.push(szenario.extent.ymin);
acc.ymax.push(szenario.extent.ymax);
});
}
// item is a szenario
else {
acc.xmin.push(item.extent.xmin);
acc.xmax.push(item.extent.xmax);
acc.ymin.push(item.extent.ymin);
acc.ymax.push(item.extent.ymax);
}
return acc;
},
{ xmin: [], xmax: [], ymin: [], ymax: [] }
);
// Prepare an extent with the smallest xmin, ymin and the biggest xmax, ymax to have all szenarios in it
const calculatedGroupExtent: __esri.Extent = new EsriExtent({
xmax: Math.max(...coordinateValues.xmax) + 200,
xmin: Math.min(...coordinateValues.xmin) - 200,
ymax: Math.max(...coordinateValues.ymax) + 200,
ymin: Math.min(...coordinateValues.ymin) - 200,
spatialReference: { wkid: 2056 },
});
显然它不是真正可读的。如果不添加许多 "readability constants"(因此没有任何改进)
,我找不到一个漂亮的方法来简化它您可以制作一个辅助函数,它接受一个 szenario
对象并将每个 ['xmin', 'xmax', 'ymin', 'ymax']
属性推送到适当的数组。然后,在迭代项目时,您只需要测试项目是否是一个组(在这种情况下您会做 item.szenarios.forEach(addSzenario)
),否则添加单个 szenario:addSzenario(item.extent)
const props = ['xmin', 'xmax', 'ymin', 'ymax'];
const coordinateValues = Object.fromEntries(
props.map(prop => [prop, []])
);
const addSzenario = (szenario) => {
for (const prop of props) {
coordinateValues[prop].push(szenario[prop]);
}
};
for (const item of selectedGroup.items) {
// item is a group
if (item.szenarios) {
item.szenarios.forEach(addSzenario);
} else {
addSzenario(item.extent);
}
}
您可以使用 reduce 来计算最大值和最小值。
const getVal = (item) => {
return item.szenarios ? szenario.extent[key] : item.extent[key];
}
const getMin = (group, key) => {
return group.items.reduce((acc, item) => {
return Math.min(acc, getVal(item));
}, Number.MAX_SAFE_INTEGER);
}
const getMax = (group, key) => {
return group.items.reduce((acc, item) => {
return Math.max(acc, getVal(item));
}, Number.MIN_SAFE_INTEGER);
}
const xmin = getMin(selectedGroup, "xmin");
const xmax = getMin(selectedGroup, "xmax");
const ymin = getMin(selectedGroup, "ymin");
const ymax = getMin(selectedGroup, "ymax");
我想出了两个答案的混合:
const pointIdentifiers = ['xmin', 'xmax', 'ymin', 'ymax'];
// Get all coordinates of the group's szenarios
const coordinateValues = selectedGroup.items.reduce((acc, item) => {
// Differenciate if item is a szenario itself or a group (with szenarios)
const szenarios = item.szenarios ? item.szenarios : [item];
// Add every point for every szenario
szenarios.forEach((valueItem) => {
pointIdentifiers.forEach((identifier) => {
acc[identifier].push(valueItem.extent[identifier]);
});
});
return acc;
}, Object.fromEntries(pointIdentifiers.map((prop) => [prop, []])));
// Prepare an extent with the smallest xmin, ymin and the biggest xmax, ymax to have all szenarios in it
const calculatedGroupExtent: __esri.Extent = new EsriExtent({
xmax: Math.max(...coordinateValues.xmax) + 200,
xmin: Math.min(...coordinateValues.xmin) - 200,
ymax: Math.max(...coordinateValues.ymax) + 200,
ymin: Math.min(...coordinateValues.ymin) - 200,
spatialReference: { wkid: 2056 },
});