zoukankan      html  css  js  c++  java
  • Thinking in Ramda: Immutability and Arrays

    Thinking in Ramda: Immutability and Arrays

    This post is Part 7 of a series about functional programming called Thinking in Ramda.

    In Part 6, we talked about working with JavaScript objects in a functional and immutable way.

    In this post, we’ll do the same for arrays.

    Reading Array Elements

    In Part 6, we learned about various Ramda functions for reading object properties, including prop, pick, and has. Ramda has even more methods for reading array elements.

    The array equivalent of prop is nth; the equivalent of pick is slice, and the equivalent of has is contains. Let’s look at those.

    Reading Array Elements

    const numbers = [10, 20, 30, 40, 50, 60]
    nth(3, numbers) // => 40  (0-based indexing)
    nth(-2, numbers) // => 50 (negative numbers start from the right)
    slice(2, 5, numbers) // => [30, 40, 50] (see below)
    contains(20, numbers) // => true
    

    Slice takes two indexes and returns the sub array starting at the first index (0-based) and including all of the elements up to, but not including the second index.

    Accessing the first (nth(0)) and last (nth(-1)) elements is quite common, so Ramda provides shortcuts for those special cases, head and last. It also provides functions for accessing all-but-the-first element (tail), all-but-the-last element (init), the first N elements (take(N)), and the last N elements (takeLast(N)). Let’s see these in action.

    More Array Reading

    const numbers = [10, 20, 30, 40, 50, 60]
    head(numbers) // => 10
    tail(numbers) // => [20, 30, 40, 50, 60]
    last(numbers) // => 60
    init(numbers) // => [10, 20, 30, 40, 50]
    take(3, numbers) // => [10, 20, 30]
    takeLast(3, numbers) // => [40, 50, 60]
    

    Adding, Updating, and Removing Array Elements

    For objects, we learned about assoc, dissoc, and omit for adding, updating, and removing properties.

    Because arrays are an ordered data structure, there are several methods that do the same job as assoc. The most general are insert and update, but Ramda also provides append and prepend for the common case of adding elements at the beginning or end of the array. insert, append, and prepend add new elements to the array; update “replaces” an element with a new value.

    As you might expect from a functional library, all of these functions return a new array with the desired changes; the original array is never changed.

    Adding and Updating Elements

    const numbers = [10, 20, 30, 40, 50, 60]
    insert(3, 35, numbers) // => [10, 20, 30, 35, 40, 50, 60]
    append(70, numbers) // => [10, 20, 30, 40, 50, 60, 70]
    prepend(0, numbers) // => [0, 10, 20, 30, 40, 50, 60]
    update(1, 15, numbers) // => [10, 15, 30, 40, 50, 60]
    

    For combining two objects into one, we learned about merge. Ramda provides concat for doing the same with arrays.

    concat

    const numbers = [10, 20, 30, 40, 50, 60]
    concat(numbers, [70, 80, 90]) // => [10, 20, 30, 40, 50, 60, 70, 80, 90]
    

    Note that the second array is appended to the first. This looks right when used by itself, but as with merge, it may not do what you expect when used in a pipeline. I find it useful to define a helper function, concatAfter:

    const concatAfter = flip(concat)
    

    for use in pipelines.

    Ramda also provides several options for removing elements. remove removes elements by index, while without removes them by value. There’s also drop and dropLast for the common case of removing elements from the beginning or end of the array.

    Removing Elements

    const numbers = [10, 20, 30, 40, 50, 60]
    remove(2, 3, numbers) // => [10, 20, 60]
    without([30, 40, 50], numbers) // => [10, 20, 60]
    drop(3, numbers) // => [40, 50, 60]
    dropLast(3, numbers) // => [10, 20, 30]
    

    Note that remove takes an index and a count whereas slice takes two indexes. This inconsistency can be confusing if you’re not aware of it.

    Transforming Elements

    As with objects, we may want to update an array element by applying a function to the original value.

    Transforming an Element the Hard Way

    const numbers = [10, 20, 30, 40, 50, 60]
    update(2, multiply(10, nth(2, numbers)), numbers) // => [10, 20, 300, 40, 50, 60]
    

    To simplify this common use case, Ramda provides adjust that works much like evolve does for objects. Unlike evolve, adjust only works for a single array element.

    Using adjust

    const numbers = [10, 20, 30, 40, 50, 60]
    adjust(2, multiply(10), numbers)
    

    Conclusion

    We now have tools for working with arrays and objects in a declarative and immutable way. This allows us to build programs out of small, functional building blocks, combining functions to do what we need to do, all without mutating our data structures.

    Next

    We’ve learned ways of reading, updating, and transforming object properties and array elements. Ramda provides a more general tool for performing these operations, the lens. Lenses shows us how they work.

  • 相关阅读:
    阿里云前端周刊
    在没有DOM操作的日子里,我是怎么熬过来的(中)
    【php学习】数组操作
    App之百度云推送
    L2-008. 最长对称子串
    整数划分问题之递归法
    分治法之归并排序(递归+分治)
    L2-005. 集合相似度
    分治法之棋盘覆盖问题
    L2-003. 月饼
  • 原文地址:https://www.cnblogs.com/cuishengli/p/15210313.html
Copyright © 2011-2022 走看看