我正在尝试减少对象数组(在我的例子中是配置值)。 我的数组看起来像这样:
const settings = [
{room: null, key: 'radioEnabled', value: true},
{room: 24, key: 'radioEnabled', value: false},
{room: 24, key: 'name', value: 'Jack'},
{room: 23, key: 'name', value: 'Mike'},
{room: 23, key: 'radioEnabled', value: false},
{room: null, key: 'tvEnabled', value: false},
];
这个数组没有任何顺序。
如果一个房间设置为 null
,这意味着它是一个全局设置。
全局设置可以被本地设置覆盖。
我正在尝试编写一个函数来获取房间的所有设置。 对于 24 号房间,它应该返回:
[
{room: 24, key: 'radioEnabled', value: false},
{room: 24, key: 'name', value: 'Jack'},
{room: null, key: 'tvEnabled', value: false},
]
返回值的顺序对我来说并不重要。 我已经能够以不止一种方式实现这一目标,但这些解决方案对我来说似乎并不那么优雅/可读。谁能提出一个更优雅的想法?
我的解决方案在下方和 jsfiddle 上.
const settings = [
{room: null, key: 'radioEnabled', value: true},
{room: 24, key: 'radioEnabled', value: false},
{room: 24, key: 'name', value: 'Jack'},
{room: 23, key: 'name', value: 'Mike'},
{room: 23, key: 'radioEnabled', value: false},
{room: null, key: 'tvEnabled', value: false},
];
const getAll_1 = function(room){
return settings.reduce( (a, b) => {
// remove all other rooms
if(b.room && b.room!== room){
return a;
}
// see if the setting is already added
let found = a.find( (setting) => {
return setting.key === b.key;
})
// we already have a local value in our return array, don't add/replace anything
if( found && found.room === room) {
return a;
}
// we have a value, but it's not local. Replace the current value with the new one
if( found ) {
const index = a.findIndex( (setting) => {
return setting.key === b.key;
})
a[index] = b;
return a;
}
// we don't have this setting at all. add it.
return a.concat(b);
}, []);
}
const getAll_2 = function(room){
return settings
// first filter out all other room settings, only keep current room and global values
.filter( (setting) => {
return setting.room === null || setting.room === room;
})
// than sort em so all local (high prio) values are up top
.sort( (a, b) => {
return (a.room > b.room) ? -1 : ( a.room < b.room ) ? 1 : 0;
})
// reduce the array, adding only global values if they are not already added as local value
.reduce( (a, b) => {
const found = a.find( (setting) => {
return setting.key === b.key;
})
if (found){
return a;
}
return a.concat(b);
}, [])
}
console.log(`Stack Overflow does not support console.table. Open your console for better representation`);
console.log(`getAll_1 response:`);
console.table(getAll_1(24));
console.log(`getAll_2 response:`);
console.table(getAll_2(24));
Check your console
最佳答案
另一种可能有助于也可能不会满足您的基本要求的方法是将其转换为更有用的格式:
const roomSettings = settings => {
const globals = settings.filter(s => s.room == null)
.reduce((all, {key, value}) => ({...all, [key]: value}), {})
return settings.filter(s => s.room != null)
.reduce((all, {room, key, value}) => ({
...all,
[room]: {...(all[room] || globals), [key]: value}
}), {} )
}
const settings = [{"key": "radioEnabled", "room": null, "value": true}, {"key": "radioEnabled", "room": 24, "value": false}, {"key": "name", "room": 24, "value": "Jack"}, {"key": "name", "room": 23, "value": "Mike"}, {"key": "radioEnabled", "room": 23, "value": false}, {"key": "tvEnabled", "room": null, "value": false}, {"key": "name", "room": 25, "value": "Beth"}]
console.log(roomSettings(settings))
请注意,这会返回如下内容:
{
23: {
radioEnabled: false,
tvEnabled: false,
name: "Mike"
},
24: {
radioEnabled: false,
tvEnabled: false,
name: "Jack"
},
25: {
radioEnabled: true,
tvEnabled: false,
name: "Beth"
}
}
(我添加了 'Beth' 至少有一个不是 false
/false
。)
这种格式看起来更有用,但它肯定不适合你。
关于javascript - 优雅的reduce函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54463177/