我有一个带有设置的 JSON 对象,与此类似:
var settings = {
tab1: {
active: true,
selectOrder: 1,
selected: false
},
tab2: {
active: true,
selectOrder: 2,
selected: false
},
tab3: {
active: false,
selectOrder: 0,
selected: false
}
};
现在,我的目标是将具有最低“selectedOrder”的事件元素的“selected”属性设置为“true”。在此示例中,我应该为“tab1”元素设置“selected”(“tab3”的 selectedOrder 为 0 但未激活)。
其背后的原因是根据其优先级(selectOrder)选择第一个事件选项卡。
我的解决方案是:
function selectFirstActiveTab(visibilitySettings) {
var selected = 1000;
var answer = jQuery.extend({}, visibilitySettings);
Object.keys(answer).forEach((key) => {
if (answer[key].active && answer[key].selectOrder <= selected) {
selected = answer[key].selectOrder;
}
});
Object.keys(answer).forEach((key) => {
answer[key].selected = (answer[key].selectOrder === selected) ? true : false;
});
return answer;
};
虽然这个解决方案有效,但它似乎是一个糟糕的解决方案。
我的问题是:
是否有更好的“函数式编程”方法? (例如使用map/reduce等)
我觉得我的设置对象结构不佳。也许我应该选择一个对象数组而不是这个 JSON?选择这样的 JSON 的原因是为了更简单地绑定(bind)到我的模板(类似于“{{settins.tab1.selected}}” - 比在我的 html 中查找它更简单)。这里更好的方法应该是什么?
最佳答案
- 对于
对象
上的map和reduce,您可以使用Underscore :
function selectFirstActiveTab(visibilitySettings) {
// Clone input, with selected set to false.
var answer = _.mapObject(visibilitySettings, (item, key) => {
return {active: item.active, selectOrder: item.selectOrder, selected: false};
});
// Find the min among all value.
var minObj = _.reduce(answer, (min, item) => {
return (item.active && item.selectOrder < min.selectOrder) ? item : min;
}, {active: true, selectOrder: Number.MAX_SAFE_INTEGER});
// Set min to selected.
minObj.selected = true;
return answer;
};
或普通 JavaScript:
function selectFirstActiveTab(visibilitySettings) {
var keys = Object.keys(visibilitySettings);
// Create a cloned obj, like map
var answer = {};
keys.forEach((key) => {
var cloneTarget = visibilitySettings[key];
answer[key] = {
active: cloneTarget.active,
selectOrder: cloneTarget.selectOrder,
selected: false
};
});
// Convert key => value map to an array of value, then reduce it to find min.
var minimun = keys.map((key) => answer[key]).reduce((min, item) => {
return (item.active && item.selectOrder < min.selectOrder) ? item : min;
}, {active: true, selectOrder: Number.MAX_SAFE_INTEGER});
// Set min to selected.
minimun.selected = true;
return answer;
};
- 它不是
JSON
,它只是一个带有一些键值映射的普通Object
,我们将其用作Map
。如果输入是一个数组,则应用上述逻辑可能会更容易:
var settings = [
{
name: 'tab1',
active: true,
selectOrder: 1,
selected: false
},
{
name: 'tab2',
active: true,
selectOrder: 2,
selected: false
},
{
name: 'tab3',
active: false,
selectOrder: 0,
selected: false
}
];
由于原生 javascript 支持在数组
上进行归约/映射。然而,像 lodash 这样的库一样多, underscore只需让reduce/map在对象上可用即可。你可以
只需选择最适合您需要的一个(因为有很多类似的库使您能够通过对象进行映射/减少)。
关于javascript - 编辑 JSON 对象 - 寻找更好的功能方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33328500/