[英]How to translate this javascript code into functional way (better using Ramdajs)?
[英]Translate this code in functional javascript (aggregate 2 array in a map)
我剛讀過關於反應式編程的內容 ,我對此很感興趣。 所以我決定修改我的函數式編程技巧。 我不知道這是不是正確的地方。
我有兩個數組,一個標簽和一個包含標簽的任務。 我想聚合這兩個並帶有tasksByTagName
。 我試圖使用lodash,但我沒有設法以可讀的方式做到這一點,所以我發布了我用正常for
語句做的。
我更感興趣的是理解如何以基於流的方式思考,例如將我的聚合函數視為兩個流之間的轉換,如上面鏈接的反應性編程文章所示。
那么,讓我們從數據開始:
var tags = [
{ id: 1, name: 'Week 26' },
{ id: 2, name: 'week 27' },
{ id: 3, name: 'Week 25' },
{ id: 4, name: 'Week 25' }
];
var tasks = [
{
"name": "bar",
"completed": false,
"tags": [
{ "id": 1 },
{ "id": 2 }
]
},
{
"name": "foo",
"completed": true,
"tags": [
{ "id": 1 }
]
},
{
"name": "dudee",
"completed": true,
"tags": [
{ "id": 3 },
{ "id": 1 },
{ "id": 4 }
]
}
];
這是我的一段代碼:
var _ = require('lodash');
function aggregate1(tasks, tags) {
var tasksByTags = {};
for(var t in tasks) {
var task = tasks[t];
for(var i=0; i<task.tags.length; ++i) {
var tag = task.tags[i];
if( !tasksByTags.hasOwnProperty(tag.id) ) {
tasksByTags[tag.id] = [];
}
tasksByTags[tag.id].push(task.name);
}
}
var tagById = {};
for(var t in tags) {
var tag = tags[t];
tagById[tag.id] = tag.name;
}
var tasksByTagsName = _.mapKeys(tasksByTags, function(v, k) {
return tagById[k];
})
return tasksByTagsName;
}
module.exports.aggregate1 = aggregate1;
為了完整性,這也是測試數據的測試:
var tags = [
{ id: 1, name: 'Week 26' },
{ id: 2, name: 'week 27' },
{ id: 3, name: 'Week 25' },
{ id: 4, name: 'Week 25' }
];
var tasks = [
{
"name": "bar",
"completed": false,
"tags": [
{ "id": 1 },
{ "id": 2 }
]
},
{
"name": "foo",
"completed": true,
"tags": [
{ "id": 1 }
]
},
{
"name": "dudee",
"completed": true,
"tags": [
{ "id": 3 },
{ "id": 1 },
{ "id": 4 }
]
}
];
var goodResults1 = {
'Week 26': [ 'bar', 'foo', 'dudee' ],
'week 27': [ 'bar' ],
'Week 25': [ 'dudee' ]
};
var assert = require('assert')
var aggregate1 = require('../aggregate').aggregate1;
describe('Aggegate', function(){
describe('aggregate1', function(){
it('should work as expected', function(){
var result = aggregate1(tasks, tags);
assert.deepEqual(goodResults1, result);
})
})
})
下面的方法轉換為標簽對象的對象減少。 在惰性求值的幫助下,下面的過程只運行tags.length
x tasks.length
次。 如果你不熟悉懶惰的評估,這里有一個參考 。
的script.js
function agregateTasks(tasks, tags) {
return _.reduce(tags, function(result, tag) {
// chain tasks to lazy evaluate
result[tag.name] = _(tasks)
// get all tasks with tags that contains tag.id
.filter({ tags: [_.pick(tag, 'id')]})
// get all names
.pluck('name')
// concatenate existing task names if there are
.concat(result[tag.name] || [])
// only unique task name values
.uniq()
// run lazy evaluation
.value();
return result;
}, {});
}
script.spec.js
describe('aggregate()', function(){
var tags, tasks, expectedResults;
beforeEach(function() {
tags = [
{ id: 1, name: 'Week 26' },
{ id: 2, name: 'week 27' },
{ id: 3, name: 'Week 25' },
{ id: 4, name: 'Week 25' }
];
tasks = [
{
"name": "bar",
"completed": false,
"tags": [
{ "id": 1 },
{ "id": 2 }
]
},
{
"name": "foo",
"completed": true,
"tags": [
{ "id": 1 }
]
},
{
"name": "dudee",
"completed": true,
"tags": [
{ "id": 3 },
{ "id": 1 },
{ "id": 4 }
]
}
];
expectedResults = {
'Week 26': [ 'bar', 'foo', 'dudee' ],
'week 27': [ 'bar' ],
'Week 25': [ 'dudee' ]
};
});
it('should work as expected', function() {
var result = aggregateTasks(tasks, tags);
expect(result).toEqual(expectedResults);
});
});
這是一種方法: https : //jsfiddle.net/ok6wf7eb/
function aggregate(tasks, tags) {
// make an id: tag map
var tagMap = tags.reduce(function(map, tag) {
map[tag.id] = tag.name;
return map;
}, {});
// collect tasks by tag
return tasks.reduce(function(map, task) {
// loop through task tags
task.tags.forEach(function(tag) {
// get tag name by id
var tagId = tagMap[tag.id];
// get array, making it on the fly if needed
var tasks = map[tagId] || (map[tagId] = []);
// add the new task name
tasks.push(task.name);
});
return map;
}, {});
}
這使用reduce
作為一種稍微更“功能”的方法解決問題,盡管為了易讀性,我永遠不能確定它有多大的收益
var collector = {};
items.forEach(function(item) {
// add to collector
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.