How do you like the following idea? I can create a PR if you think it's good.
swap(index1, index2, array)
Swap the values at index1 and index2 of array.
Let's say I have a list of UI elements, each in a table row.
Now I want to move one element up or down. The straightforward way is to swap it with its siblings.
test('swap two elements in an array', () => {
expect(swap(0, 2, [1, 2, 3])).toEqual([3, 2, 1])
expect(swap(1, 0, [1, 2, 3])).toEqual([2, 1, 3])
})
// return the original array if any of the indexes is out of bound.
test('swap index out of bound', () => {
expect(swap(0, 3, [1, 2, 3])).toEqual([1, 2, 3])
expect(swap(-1, 2, [1, 2, 3])).toEqual([1, 2, 3])
})
export const swap = R.curry((index1, index2, list) => {
if (index1 < 0 || index2 < 0 || index1 > list.length - 1 || index2 > list.length - 1) {
return list // index out of bound
}
const value1 = list[index1]
const value2 = list[index2]
return R.pipe(
R.set(R.lensIndex(index1), value2),
R.set(R.lensIndex(index2), value1)
)(list)
})
My take is that this belongs in the Cookbook. This is the first time I've heard a request for it.
I actually need a feature like this while working with react and redux. This is useful, when you need to change the order of elements in a CMS-like situation.
For anyone interested, here is swap function for multidimensional arrays :
swapDeep([1, 1], [0, 0], list)
const swapDeep = a => b => list => {
const lensPathA = lensPath(a)
const lensPathB = lensPath(b)
const valueA = view(lensPathA, list)
const valueB = view(lensPathB, list)
const noPath = flip(hasPath)
const outOfBounds = both(noPath(a), noPath(a))
const makeSwap = compose(
set(lensPathB, valueA),
set(lensPathA, valueB)
)
return unless(
outOfBounds,
makeSwap
)(list)
}