簡體   English   中英

在功能javascript(地圖中的聚合2數組)中翻譯此代碼

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM