javascript - 优雅的reduce函数

标签 javascript arrays ecmascript-6

我正在尝试减少对象数组(在我的例子中是配置值)。 我的数组看起来像这样:

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/

相关文章:

javascript - 如何根据索引数组更改元素的状态?

javascript - 从数据绑定(bind)外部引用 knockout 数组并且没有路径知识

javascript - JQuery 脚本不能运行两次

javascript - 为什么 array.splice() 在用于变量的副本时会更改变量?

c - 奇怪的枚举用法

javascript - for 循环后返回一个值

javascript - 在 Javascript 中删除和更新数组而不进行突变

javascript - 如何在浏览器中正确实现异步事件处理程序

javascript - 当 ng-if 添加/删除元素时收到通知

javascript - 使用 d3.js 创建一条穿过某些点的线