I'm one of the founders of Ramda, and a big fan. But Ramda was mostly built in the days before we could count on ES6+ techniques, and, while I still use it a lot, certain things are just as easy now with vanilla JS. Here is my approach, which still uses the insert and remove Ramda helper functions:
const moveItem = (
srcKey, srcIdx, destKey, destIdx, obj,
{[String (srcKey)]: src, [String (destKey)]: dest, ...rest} = obj
) => ({
[srcKey]: remove (srcIdx, 1, src),
[destKey]: insert (destIdx, src [srcIdx], dest || []),
...rest
})
const stuff = {"31": [{"id": "11", "title": "Just move me pls"}, {"id": "12", "title": "Ramda 123"}], "33": [{"id": "3", "title": "Ramda jedi"}], "4321": [{"id": "1", "title": "Hello Ramda"}]}
console.log (
moveItem (31, 0, 33, 1, stuff)
)
console.log ( // destination doesn't exist
moveItem (31, 0, 35, 1, stuff)
)
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script>const {remove, insert} = R </script>
Note that dest || [] is to handle the case when the destination object does not exist.
I would never introduce Ramda just to get these helper functions, as it's easy enough to write the equivalent without them with only a little extra code:
const moveItem = (
srcKey, srcIdx, destKey, destIdx, obj,
{[String (srcKey)]: src, [String (destKey)]: dest, ...rest} = obj
) => ({
[srcKey]: [... src .slice (0, srcIdx), ... src .slice (srcIdx + 1)],
[destKey]: [...(dest || []) .slice (0, destIdx), src [srcIdx], ...(dest || []) .slice (destIdx)],
...rest
})
But, as I usually have Ramda included in my projects, I still tend to think of its functions right away.
I don't think of this as necessarily better than Ori Drori's lens-based solution. Reaching for lenses when you have to focus on part of a structure is probably a good habit. But it's not necessarily worse either. Writing code as simply as possible has some powerful benefits, and I do find this a bit simpler.
One other thing. Regarding this comment to Nina's answer:
I know about native solution, but I want to solve this with more functional way:) (with Ramda)
I dislike Nina's solution because of the inherent mutation, and that's a perfectly reasonable reason to reject it. But "with Ramda" should only be the goal if this is an exercise in learning Ramda. If your main unit of work is the function and your functions are pure and you don't mutate user data, then you are doing functional programming, regardless of any libraries you might be using.