我有一个系统,我希望在用户执行某些操作时向用户显示有用的信息。但是,根据用户的不同,如果我们知道他们已经熟悉特定操作,我们可能会选择不显示该消息。
我有两个多维数组,我需要比较,以确定是否应该显示该消息。一个包含用户分类,一个包含所有消息。
我的问题是,编码风格在可能的情况下更喜欢使用Lodash助手,我对它并不太熟悉。
下面的代码可以满足我的需要,但它显然不是很好或不具备性能。
// user classification for each type of action
const classifications = [
{
status: 'basic',
actionTypes: [
'copy', 'paste'
],
},
{
status: 'basic',
actionTypes: [
'buy', 'sell'
],
},
{
status: 'professional',
actionTypes: [
'drag', 'drop'
],
}
];
// array of messages for each set of actions
const messages = [
{
message: 'foo',
actionTypes: [
'copy', 'paste'
],
},
{
message: 'bar',
actionTypes: [
'buy', 'sell'
],
},
{
message: 'baz',
actionTypes: [
'drag', 'drop'
],
}
];
// returns only messages for which the user is not professional
function getMappedMessages() {
const basicClassifications = _.filter(classifications, ['status', 'basic']);
const filteredMessages = [];
for (let i = 0; i < basicClassifications.length; i++) {
for (let j = 0; j < basicClassifications[i].actionTypes.length; j++) {
for (let k = 0; k < messages.length; k++) {
if (_.includes(messages[k].actionTypes, basicClassifications[i].actionTypes[j])) {
filteredMessages.push(messages[k]);
break;
}
}
}
}
return filteredMessages;
}
console.log(getMappedMessages());
<script src="https://cdn.jsdelivr.net/lodash/4/lodash.min.js"></script>
如您所见,每组操作(例如“复制”和“粘贴”)都有一条消息,并且用户具有与分类一起的相应操作集。如果分类不合格,我匹配两个内部数组(对于外部数组中的每个对象),并返回仅包含“基本”消息的对象。
这两个数组可能是相同的(所以我可以直接比较,也许用_.difference
?),但我不确定。
如何让这种怪物更具可读性和高效性?我应该做一些扁平化吗?
数据来自两个独立的端点,我无法修改结构。
答案 0 :(得分:2)
_.isEqual()
会做你想做的事。
至于清理它,我建议将其展平和/或将其分解为功能,这样你至少可以更好地了解正在发生的事情。
答案 1 :(得分:1)
有很多方法可以改进代码。我做的第一件事就是执行过滤,map,reduce。
const classifications = [{
status: 'basic',
actionTypes: [ 'copy', 'paste'],
},
{
status: 'basic',
actionTypes: [ 'buy', 'sell' ],
},
{
status: 'professional',
actionTypes: [ 'drag', 'drop' ],
}
];
const messages = [{
message: 'foo',
actionTypes: [ 'copy', 'paste' ],
},
{
message: 'bar',
actionTypes: ['buy', 'sell'],
},
{
message: 'baz',
actionTypes: [ 'drag', 'drop' ],
}
];
function getBasicActionTypes() {
return classifications
.filter(c => c.status === 'basic')
.map(c => c.actionTypes)
.reduce((a,b) => a.concat(b), []);
}
function getMessages(actionTypes) {
return messages
.filter(m => m.actionTypes.some(a => actionTypes.indexOf(a) > -1));
}
function getMessagesFromSet(actionTypeSet) {
return messages
.filter(m => m.actionTypes.some(a => actionTypeSet.has(a)));
}
const arr = getBasicActionTypes();
const m1 = getMessages(arr);
const s = new Set(arr);
const m2 = getMessagesFromSet(s);
console.log(m2);
&#13;
<script src="https://cdn.jsdelivr.net/lodash/4/lodash.min.js"></script>
&#13;
我必须使用示例结果数组m1
和m2
,它们都包含相同的元素。区别在于m2
来自ES6 Set,但应该更快。
答案 2 :(得分:1)
当然,大部分都可以在纯ES6 / ES7中实现。但是你要求lodash,所以这里有一些惯用的lodash ...
Chaining真的很酷,因为它基本上为你提供了一个值的包装器(这就是为什么你在使用chain()时必须调用value()的原因。
它允许你按顺序链接任何你想要的lodash函数,你不受输出数组或对象等的限制。:
const getMappedMessages = (classifications, messages) => {
const classActionsMap = _.chain(classifications)
.filter(['status', 'basic'])
.map(_.get('actionTypes')))
.reduce((prev, curr) => {
const key = JSON.stringify(curr);
Object.assign(prev, {[key]: true})
}, {})
.value();
return _.filter(messages, msg => classActionsMap[msg.actionTypes]);
}
答案 3 :(得分:1)
您可以使用lodash#keyBy
将所有分类编入其actionTypes
作为键的索引。使用索引分类作为使用lodash#filter
保留不属于professional
状态的邮件的方式。
// index all classifications by their actionTypes
var indexes = _.keyBy(classifications, 'actionTypes');
// get all non-profiessional messages
var nonProMessages = _.filter(messages, function(message) {
// path to get the status matching the
// actionType of this message
var key = [message.actionTypes, 'status'];
// compare the status represented by the message
return _.get(indexes, key) !== 'professional';
});
// user classification for each type of action
const classifications = [{
status: 'basic',
actionTypes: [
'copy', 'paste'
],
},
{
status: 'basic',
actionTypes: [
'buy', 'sell'
],
},
{
status: 'professional',
actionTypes: [
'drag', 'drop'
],
}
];
// array of messages for each set of actions
const messages = [{
message: 'foo',
actionTypes: [
'copy', 'paste'
],
},
{
message: 'bar',
actionTypes: [
'buy', 'sell'
],
},
{
message: 'baz',
actionTypes: [
'drag', 'drop'
],
}
];
// index all classifications by their actionTypes
var indexes = _.keyBy(classifications, 'actionTypes');
// get all non-profiessional messages
var nonProMessages = _.filter(messages, function(message) {
// path to get the status matching the
// actionType of this message
var key = [message.actionTypes, 'status'];
// compare the status represented by the message
return _.get(indexes, key) !== 'professional';
});
console.log(nonProMessages);
body > div { min-height: 100%; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>