若要改變 Array 中指定 Index 值,Ramda 提供了 update()
,可自行傳入 Index 與 Value 改變之。
Version
macOS Mojave 10.15.1
VS Code 1.40.2
Quokka 1.0.262
Ramda 0.26.1
Imperative
let data = [1, 2, 3]
let update = idx => val => arr => {
let result = arr.slice()
result[idx] = val
return result
}
update(1)(4)(data) // ?
data // ?
update()
最直覺會使用 []
直接改變 array,但別忘了 function 對於 array 與 object 是 pass by reference,因此直接修改 argument 相當於也修改了原始 data,有嚴重 side effect。
因此比較好的作法是使用 slice()
將傳進 array 再 clone 一份 result
出來,再針對 result
做 []
處理。
let data = [1, 2, 3]
let update = idx => val => arr => {
let result = []
for(let i = 0; i < arr.length; i++) {
if (i === idx) result[i] = val
else result[i] = arr[i]
}
return result
}
update(1)(4)(data) // ?
data // ?
比較好的做法是另外建立回傳的 result
array,乖乖使用 for
loop 判斷 index 並改變其 value,如此就不會有 side effect。
Array.prototype.reduce()
let data = [1, 2, 3]
let update = idx => val => arr => arr.reduce((a, x, i) =>
i === idx ? [...a, val] : [...a, x]
, [])
update(1)(4)(data) // ?
data // ?
回傳是單一 array 且可用 for
loop 實現,就可改用 reduce()
改寫,且也沒有 side effect。
別忘了 reduce()
的第三個 parameter 為 index,因此可用來判斷指定 index。
Array.prototype.splice()
let data = [1, 2, 3]
let update = idx => val => arr => {
let result = arr.slice()
result.splice(idx, 1, val)
return result
}
update(1)(4)(data) // ?
data //
Array.prototype.splice()
是很強的 method,可用來對 array 處理 insert、update 與 delete,因此 update()
也可改用 splice()
實踐,唯 splice()
有很大 side effect,須小心使用。
因此比較好的作法是使用 slice()
將傳進 array 再 clone 一份 result
出來,再針對 result
做 splice()
處理。
Ramda
import { update } from 'ramda'
let data = [1, 2, 3]
update(1)(4)(data) // ?
data // ?
Ramda 提供了 update()
,可直接使用,且沒有 side effect。
update()
Number → a → [a] → [a]
使用 value 改變 array 中指定 index 值
Number
:指定 index 值
a
:改變 index 的 value
[a]
:data 為 array
[a]
:回傳改變過 array
Conclusion
Array.prototype.splice()
雖然好用,但要小心其 side effect,必須先用slice()
clone 一份出來再使用adjust()
與update()
很類似,唯adjust()
傳入 function,而update()
傳入 value
Reference
MDN, Array.prototype.reduce()
MDN, Array.prototype.splice()
MDN, Array.prototype.slice()
Ramda, update()