[翻譯]map和reduce,處理數據結構的利器

原文地址: https://codeburst.io/writing-javascript-with-map-reduce-980602ff2f2f
做者: Shivek Khurana
簡介:本文是一份編寫優雅、簡潔和函數式ES6代碼的快捷清單。

現現在JavaScript有許多問題,可是詞法並非其中之一。不論是三元運算符,仍是map/reduce等ES6方法,亦或是擴展運算符(...)都是很是強大的工具。 javascript

除了可以保證可讀性以及準確性,這些方法還有助於實現不可變性,由於這些方法會返回新的數據,而處理前的原始數據並不會被修改。這樣的處理風格很適合redux以及Fractaljava

話很少說,讓咱們開始吧。react

一個簡單的reduce實踐

當你想要將多個數據放進一個實例中時,你可使用一個reducer。git

const posts = [
  {id: 1, upVotes: 2},
  {id: 2, upVotes: 89},
  {id: 3, upVotes: 1}
];
const totalUpvotes = posts.reduce((totalUpvotes, currentPost) =>     
  totalUpvotes + currentPost.upVotes, //reducer函數
  0 // 初始化投票數爲0
);
console.log(totalUpvotes)//輸出投票總數:92

傳給reduce的第一個參數函數還能夠增長2個參數:github

  1. 第三個參數:每一個元素在原數據結構中的位置,好比數組下標。
  2. 第四個參數:調用reduce方法的數據集合,好比例子中的posts。
    因此,一個reducer的徹底體應該是下面這樣的:
collection.reduce(
  (accumulator, currentElement, currentIndex, collectionCopy) => 
    {/*function body*/},
    initialAccumulatorValue
);

一個簡單的map實踐

map方法的做用在於處理流式數據,好比數組。咱們能夠把它想象成全部元素都要通過的一個轉換器。redux

const integers = [1, 2, 3, 4, 6, 7];
const twoXIntegers = integers.map(i => i*2);
// twoXIntegers如今是 [2, 4, 6, 8, 12, 14],而integers不發生變化。

一個簡單的find實踐

find返回數組或相似結構中知足條件的第一個元素。數組

const posts = [
  {id: 1, title: 'Title 1'},
  {id: 2, title: 'Title 2'}
];
// 找出id爲1的posts
const title = posts.find(p => p.id === 1).title;

一個簡單的filter實踐

filter方法能夠篩除數組和相似結構中不知足條件的元素,並返回知足條件的元素組成的數組。數據結構

const integers = [1, 2, 3, 4, 6, 7];
const evenIntegers = integers.filter(i => i%2 === 0);
// evenIntegers的值爲[2, 4, 6]

向數組中新增元素

若是你要建立一個無限滾動的ui組件(好比本文後面提到的例子),可使用擴展運算符這個很是有用的詞法。app

const books = ['Positioning by Trout', 'War by Green'];
const newBooks = [...books, 'HWFIF by Carnegie'];
// newBooks are now ['Positioning by Trout', 'War by Green', 'HWFIF // by Carnegie']

爲一個數組建立視圖

若是須要實現用戶從購物車中刪除物品,可是又不想破壞原來的購物車列表,可使用filter方法。函數

const myId = 6;
const userIds = [1, 5, 7, 3, 6];
const allButMe = userIds.filter(id => id !== myId);
// allButMe is [1, 5, 7, 3]
譯者注:這裏我猜想做者是不想修改原來的數組因此使用的filter,可是不能理解爲何要舉購物車的例子。

向對象數組添加新元素

const books = [];
const newBook = {title: 'Alice in wonderland', id: 1};
const updatedBooks = [...books, newBook];
//updatedBooks的值爲[{title: 'Alice in wonderland', id: 1}]

books這個變量咱們沒有給出定義,可是沒關係,咱們使用了擴展運算符,它並不會所以失效。

爲對象新增一組鍵值對

const user = {name: 'Shivek Khurana'};
const updatedUser = {...user, age: 23};
//updatedUser的值爲:{name: 'Shivek Khurana', age: 23}

使用變量做爲鍵名爲對象添加鍵值對

const dynamicKey = 'wearsSpectacles';
const user = {name: 'Shivek Khurana'};
const updatedUser = {...user, [dynamicKey]: true};
// updatedUser is {name: 'Shivek Khurana', wearsSpectacles: true}

修改數組中知足條件的元素對象

const posts = [
  {id: 1, title: 'Title 1'},
  {id: 2, title: 'Title 2'}
];
const updatedPosts = posts.map(p => p.id !== 1 ?
  p : {...p, title: 'Updated Title 1'}
);
/*
updatedPosts is now 
[
  {id: 1, title: 'Updated Title 1'},
  {id: 2, title: 'Title 2'}
];
*/

找出數組中知足條件的元素

const posts = [
  {id: 1, title: 'Title 1'},
  {id: 2, title: 'Title 2'}
];
const postInQuestion = posts.find(p => p.id === 2);
// postInQuestion now holds {id: 2, title: 'Title 2'}
譯者注:奇怪啊,這不就是以前find的簡單實踐嗎?

刪除目標對象的一組屬性

const user = {name: 'Shivek Khurana', age: 23, password: 'SantaCl@use'};
const userWithoutPassword = Object.keys(user)
  .filter(key => key !== 'password')
  .map(key => {[key]: user[key]})
  .reduce((accumulator, current) => 
    ({...accumulator, ...current}),
    {}
  )
;
// userWithoutPassword becomes {name: 'Shivek Khurana', age: 23}

感謝Kevin Bradley提供了一個更優雅的方法:

const user = {name: 'Shivek Khurana', age: 23, password: 'SantaCl@use'};
const userWithoutPassword = (({name, age}) => ({name, age}))(user);

他還表示這個方法在對象屬性更少時也能發揮做用。

將對象轉化成請求串

你也許幾乎遇不到這個需求,可是有時候在別的地方會給你一點啓發。

const params = {color: 'red', minPrice: 8000, maxPrice: 10000};
const query = '?' + Object.keys(params)
  .map(k =>   
    encodeURIComponent(k) + '=' + encodeURIComponent(params[k])
  )
  .join('&')
;
// encodeURIComponent將對特殊字符進行編碼。
// query is now "color=red&minPrice=8000&maxPrice=10000"

獲取數組中某一對象的下標

const posts = [
  {id: 13, title: 'Title 221'},
  {id: 5, title: 'Title 102'},
  {id: 131, title: 'Title 18'},
  {id: 55, title: 'Title 234'}
];
// 找到id爲131的元素
const requiredIndex = posts.map(p => p.id).indexOf(131);
譯者注:這裏我以爲方法很繁瑣。可使用findIndex方法: const requiredIndex = posts.findIndex(obj=>obj.id===131);,一樣能獲取到下標值2。

做者總結

有了這些強大的方法,我但願你的代碼會變得愈來愈穩定和一絲不苟。當你的團隊中有一個新的開發者加入時,能夠向他推薦這篇文章,讓他了解之前不知道的祕密。

這個翻譯項目纔開始,之後會翻譯愈來愈多的做品。我會努力堅持的。
項目地址: https://github.com/WhiteYin/translation
相關文章
相關標籤/搜索