[英]Move object from array A to array B. Ramda.js
通过move 移动数组中的项目非常简单,但不幸的是,它并不像往常一样适合我的情况。
例如,我需要将索引为 0 的对象从组 #31 移动到 #33,并将目标数组中对象的新索引设置为 1。
source_group_id
= 31source_object_index
= 0destination_group_id
= 33destination_object_index
= 1数据对象模型:
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"
}
]
}
有谁知道如何解决这个问题?
在普通的 Javascript 中, Array#splice
工作得很好。
const stuff = { 31: [{ id: "11", title: "just move me pls" }, { id: "12", title: "ramda 123" }], 33: [{ id: "3", title: "..." }], 4321: [{ id: "1", title: "hello Ramda" }] }; stuff['33'].splice(1, 0, ...stuff['31'].splice(0, 1)); console.log(stuff);
.as-console-wrapper { max-height: 100%;important: top; 0; }
您可以使用镜头来更改子对象,但您首先需要获取该项目。
首先使用R.view
和R.lensPath
来获取项目。 然后使用R.over
和R.lenseProp
从源键和索引( sk
, si
)处的子对象中删除项目,然后将其插入到目标键和索引( tk
, ti
)。
更新:要添加一个目标,如果键( tk
)不存在,请使用R.unless
检查R.has
是否存在tk
,如果它不使用R.assoc
添加一个空数组。
const { curry, view, lensPath, pipe, over, lensProp, remove, unless, has, assoc, insert } = R; const fn = curry(({ key: sk, idx: si }, { key: tk, idx: ti }, obj) => { const item = view(lensPath([sk, si]), obj); // get the item return pipe( over(lensProp(sk), remove(si, 1)), // remove the item from the source unless(has(tk), assoc(tk, [])), // add target if it's missing over(lensProp(tk), insert(ti, item)), // move to the target )(obj); }); const stuff = { 31: [{ id: "11", title: "just move me pls" }, { id: "12", title: "ramda 123" }], 33: [{ id: "3", title: "..." }], 4321: [{ id: "1", title: "hello Ramda" }] }; console.log(fn({ key: '31', idx: 0 }, { key: 33, idx: 1 }, stuff)); console.log(fn({ key: '31', idx: 0 }, { key: 555, idx: 1 }, stuff));
.as-console-wrapper { max-height: 100%;important: top; 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
我是 Ramda 的创始人之一,也是它的忠实粉丝。 但是 Ramda 主要是在我们可以依靠 ES6+ 技术之前的日子里构建的,虽然我仍然经常使用它,但现在使用 vanilla JS 某些事情也一样容易。 这是我的方法,它仍然使用insert
和remove
Ramda 辅助函数:
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>
请注意, dest || []
dest || []
用于处理目标对象不存在的情况。
我永远不会仅仅为了获得这些辅助函数而引入 Ramda,因为只需要一点额外的代码就可以很容易地编写没有它们的等价物:
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
})
但是,由于我通常将 Ramda 包含在我的项目中,我仍然倾向于立即想到它的功能。
我认为这不一定比 Ori Drori 基于镜头的解决方案更好。 当您必须专注于结构的一部分时,伸手去拿镜头可能是一个好习惯。 但这也不一定更糟。 尽可能简单地编写代码有一些强大的好处,我确实发现这更简单一些。
另一件事。 关于对尼娜回答的评论:
我知道本机解决方案,但我想用更实用的方式解决这个问题:)(使用 Ramda)
由于固有的突变,我不喜欢 Nina 的解决方案,这是拒绝它的完全合理的理由。 但是,如果这是学习 Ramda 的练习,那么“with Ramda”应该只是目标。 如果您的主要工作单元是函数并且您的函数是纯函数并且您不改变用户数据,那么您就是在进行函数式编程,而不管您可能使用的是什么库。
除非您需要以编程方式执行此操作,否则您可以使用 Javascript Array 方法简单地移动对象。
stuff[33][1] = stuff[31][0]
// index 1 at key 33 gets assigned index 0 at key 31
stuff[31].shift()
// remove the first array element and shift all others to a lower index
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.