使用 Ramda 映射和过滤对象
Map and filter an object using Ramda
我正在学习 Ramda
,我对如何使用 Ramda
构建下面的 lodash
链有些困惑。 Ramda
returns 函数用于它的操作而不是实际值,这似乎是函数式编程的焦点,但是在这个例子中我有第二个参数 localRegex
不是主要论点。如果不包装 Ramda
函数并使用 .apply()
或 .call()
将包装的函数参数传播到 [=12= ,似乎不可能完全复制它] 函数,这似乎比使用 lodash
.
更复杂
var _ = require("lodash")
var R = require("ramda")
var localRegex = /^.\.\/|^.\/|^\//
function getRecursiveDeps(deps, localRegex){
return _.chain(deps)
.map(function(dep){
return dep.source.value
})
.filter(function(dep){
return dep.match(localRegex)
})
.value()
}
var items = [
{
"source": {
"value": "./foo"
}
},
{
"source": {
"value": "bar"
}
}
]
console.log(getRecursiveDeps(items, localRegex))
这是我得到的,但它不起作用。
var getRecursiveDeps = R.chain(
R.map(function(dependency){
return dependency.source.value
}),
R.filter(function(value){
return value.match(localRegex)
})
)
有没有办法让 Ramda
使用主变量进行链接并向下传递 localRegex
?有没有办法在 Ramda
中复制使用 lodash
的 getRecursiveDeps
?
有很多关于 Ramda
是如何运作而 underscore
和 lodash
不是的讨论。但在这种情况下,getRecursiveDeps
是一个函数,returns 来自 lodash
的值。当您从 lodash
或 underscore
创建这样的函数时,结果是相同的,只是在包装它时需要做更多的工作,在这种情况下,使用 Ramda
的好处是什么Lodash
?
R.chain
做的事情与 _.chain
完全不同。根据当前文档,它的类型是 (a -> [b]) -> [a] -> [b]
,尽管它的实际类型更通用。将其视为“平面地图”功能。
你真正想要的是R.compose
or its left-to-right equivalent R.pipe
。
如果函数的目标是查找本地依赖项,那么在函数中嵌入模式对我来说似乎是合适的。我会这样写:
// getLocalDeps :: [{ source :: { value :: String }}] -> [String]
const getLocalDeps =
R.pipe(R.map(R.path(['source', 'value'])),
R.filter(R.test(/^[.]{0,2}[/]/)));
getLocalDeps(items); // => ['./foo']
我对 getRecursiveDeps
这个名字有点困惑,因为这个函数不是递归的。 getLocalDeps
似乎更合适。
如果您想参数化模式,我建议将 getLocalDeps
分成更小的部分:
// isLocal :: String -> Boolean
const isLocal = R.test(/^[.]{0,2}[/]/);
// getDeps :: [{ source :: { value :: String }}] -> [String]
const getDeps = R.map(R.path(['source', 'value']));
// getLocalDeps :: [{ source :: { value :: String }}] -> [String]
const getLocalDeps = R.pipe(getDeps, R.filter(isLocal));
然后您可以根据这些构建块定义其他功能:
// getNonLocalDeps :: [{ source :: { value :: String }}] -> [String]
const getNonLocalDeps = R.pipe(getDeps, R.reject(isLocal));
// getLocalJsonDeps :: [{ source :: { value :: String }}] -> [String]
const getLocalJsonDeps = R.pipe(getLocalDeps, R.filter(R.test(/[.]json$/)));
另一种方法,无需积分并保留现有的 API 是这样的:
// getLocalDeps :: [{ source :: { value :: String }}] -> RegExp -> [String]
const getLocalDeps = R.useWith(
R.flip(R.call),
R.map(R.path(['source', 'value'])),
R.pipe(R.unary(R.test), R.filter)
);
localDeps(items, localRegex); //=> ["./foo"]
函数的最后一行对我来说有点不幸,这个问题让我 open an issue 关于恢复最近对库的一些更改。可以使用多种变体:
// ...
R.pipe(regex => item => R.test(regex, item), R.filter)
//...
或
// ...
regex => R.filter(R.test(regex))
//...
但在最近对 Ramda 进行更改之前,它会很简单
// ...
R.pipe(R.test, R.filter)
//...
不过,有一件事是 Ramda 努力保持参数的逻辑顺序:那些不太可能改变的在那些更有可能改变的之前。考虑到这一点,我更喜欢这样的东西:
// getLocalDeps :: RegExp -> [{ source :: { value :: String }}] -> [String]
var getLocalDeps2 = R.useWith(
R.call,
R.pipe(R.unary(R.test), R.filter),
R.map(R.path(['source', 'value']))
);
localDeps2(localRegex, items); //=> ["./foo"]
而且感觉更干净了。而且,它允许您预定义函数并单独使用它:
myDeps = localDeps2(localRegex);
myDeps(items); //=> ["./foo"]
这就是 Ramda 的重要组成部分。
我正在学习 Ramda
,我对如何使用 Ramda
构建下面的 lodash
链有些困惑。 Ramda
returns 函数用于它的操作而不是实际值,这似乎是函数式编程的焦点,但是在这个例子中我有第二个参数 localRegex
不是主要论点。如果不包装 Ramda
函数并使用 .apply()
或 .call()
将包装的函数参数传播到 [=12= ,似乎不可能完全复制它] 函数,这似乎比使用 lodash
.
var _ = require("lodash")
var R = require("ramda")
var localRegex = /^.\.\/|^.\/|^\//
function getRecursiveDeps(deps, localRegex){
return _.chain(deps)
.map(function(dep){
return dep.source.value
})
.filter(function(dep){
return dep.match(localRegex)
})
.value()
}
var items = [
{
"source": {
"value": "./foo"
}
},
{
"source": {
"value": "bar"
}
}
]
console.log(getRecursiveDeps(items, localRegex))
这是我得到的,但它不起作用。
var getRecursiveDeps = R.chain(
R.map(function(dependency){
return dependency.source.value
}),
R.filter(function(value){
return value.match(localRegex)
})
)
有没有办法让 Ramda
使用主变量进行链接并向下传递 localRegex
?有没有办法在 Ramda
中复制使用 lodash
的 getRecursiveDeps
?
有很多关于 Ramda
是如何运作而 underscore
和 lodash
不是的讨论。但在这种情况下,getRecursiveDeps
是一个函数,returns 来自 lodash
的值。当您从 lodash
或 underscore
创建这样的函数时,结果是相同的,只是在包装它时需要做更多的工作,在这种情况下,使用 Ramda
的好处是什么Lodash
?
R.chain
做的事情与 _.chain
完全不同。根据当前文档,它的类型是 (a -> [b]) -> [a] -> [b]
,尽管它的实际类型更通用。将其视为“平面地图”功能。
你真正想要的是R.compose
or its left-to-right equivalent R.pipe
。
如果函数的目标是查找本地依赖项,那么在函数中嵌入模式对我来说似乎是合适的。我会这样写:
// getLocalDeps :: [{ source :: { value :: String }}] -> [String]
const getLocalDeps =
R.pipe(R.map(R.path(['source', 'value'])),
R.filter(R.test(/^[.]{0,2}[/]/)));
getLocalDeps(items); // => ['./foo']
我对 getRecursiveDeps
这个名字有点困惑,因为这个函数不是递归的。 getLocalDeps
似乎更合适。
如果您想参数化模式,我建议将 getLocalDeps
分成更小的部分:
// isLocal :: String -> Boolean
const isLocal = R.test(/^[.]{0,2}[/]/);
// getDeps :: [{ source :: { value :: String }}] -> [String]
const getDeps = R.map(R.path(['source', 'value']));
// getLocalDeps :: [{ source :: { value :: String }}] -> [String]
const getLocalDeps = R.pipe(getDeps, R.filter(isLocal));
然后您可以根据这些构建块定义其他功能:
// getNonLocalDeps :: [{ source :: { value :: String }}] -> [String]
const getNonLocalDeps = R.pipe(getDeps, R.reject(isLocal));
// getLocalJsonDeps :: [{ source :: { value :: String }}] -> [String]
const getLocalJsonDeps = R.pipe(getLocalDeps, R.filter(R.test(/[.]json$/)));
另一种方法,无需积分并保留现有的 API 是这样的:
// getLocalDeps :: [{ source :: { value :: String }}] -> RegExp -> [String]
const getLocalDeps = R.useWith(
R.flip(R.call),
R.map(R.path(['source', 'value'])),
R.pipe(R.unary(R.test), R.filter)
);
localDeps(items, localRegex); //=> ["./foo"]
函数的最后一行对我来说有点不幸,这个问题让我 open an issue 关于恢复最近对库的一些更改。可以使用多种变体:
// ...
R.pipe(regex => item => R.test(regex, item), R.filter)
//...
或
// ...
regex => R.filter(R.test(regex))
//...
但在最近对 Ramda 进行更改之前,它会很简单
// ...
R.pipe(R.test, R.filter)
//...
不过,有一件事是 Ramda 努力保持参数的逻辑顺序:那些不太可能改变的在那些更有可能改变的之前。考虑到这一点,我更喜欢这样的东西:
// getLocalDeps :: RegExp -> [{ source :: { value :: String }}] -> [String]
var getLocalDeps2 = R.useWith(
R.call,
R.pipe(R.unary(R.test), R.filter),
R.map(R.path(['source', 'value']))
);
localDeps2(localRegex, items); //=> ["./foo"]
而且感觉更干净了。而且,它允许您预定义函数并单独使用它:
myDeps = localDeps2(localRegex);
myDeps(items); //=> ["./foo"]
这就是 Ramda 的重要组成部分。