我是否使用了错误的 Ramda 函数,R.reduce 似乎没有工作
Am I using the wrong Ramda function, R.reduce doesn't appear to be working
给定一个初始消息字符串(实际上就像一个格式字符串),并包含随后要填充的占位符。
例如我们的初始消息是:
"GREETINGS-{year}-{mm-month}-{dd-day} - HELLO WORLD"
其中有 3 个占位符,{year},{mm-month }, {dd-day}
我想将其翻译成:
"GREETINGS-2016-06-23 - HELLO WORLD"
假设我们有一个对象数组如下:
[{
"Key": "{year}",
"Value": "2016"
}, {
"Key": "{mm-month}",
"Value": "06"
}, {
"Key": "{dd-day}",
"Value": "23"
}]
每个对象都有一个Key对应消息中的占位符字符串,以及用来替换占位符的Value。
我正在使用 R.reduce 函数,因为我们有一个值集合(具有 Key Value 属性的对象列表、字符串替换转换器函数 (tr) 和初始累加器是原始占位符字符串.
变换函数tr定义为:
let tr = (k, v) => { return { Key: k, Value: v } }
执行文本替换的rp函数定义为:
let rp = (pair, msg) => { return R.replace(pair.Key, pair.Value, msg); }
所以期望的效果是迭代列表,用字段值替换字段名称,在每次迭代中,return 部分填充的字符串,直到最后你有一个完全填充的字符串,没有占位符剩余。
我将 R.reduce 与 R.add 一起使用来模拟我的解决方案,即:
R.reduce(R.add, 0, [1,2,3,4,5]);
这对我来说似乎符合相同的模式,除非我弄错了。
这是 R.reduce 的调用,它没有按预期工作:
R.reduce(rp, place_holders, pairs)
λ R.reduce(rp, place_holders, pairs);
TypeError: str.replace is not a function
at replace (/Users/devuser/.nvm/versions/node/v10.13.0/lib/node_modules/ramda-repl/node_modules/ramda/src/replace.js:25:14)
at Object.f3 [as replace] (/Users/devuser/.nvm/versions/node/v10.13.0/lib/node_modules/ramda-repl/node_modules/ramda/src/internal/_curry3.js:35:16)
at XWrap.rp [as f] (repl:2:36)
at XWrap.module.exports.XWrap.@@transducer/step (/Users/devuser/.nvm/versions/node/v10.13.0/lib/node_modules/ramda-repl/node_modules/ramda/src/internal/_xwrap.js:10:17)
at _arrayReduce (/Users/devuser/.nvm/versions/node/v10.13.0/lib/node_modules/ramda-repl/node_modules/ramda/src/internal/_reduce.js:11:36)
at _reduce (/Users/devuser/.nvm/versions/node/v10.13.0/lib/node_modules/ramda-repl/node_modules/ramda/src/internal/_reduce.js:44:14)
at Object.f3 [as reduce] (/Users/devuser/.nvm/versions/node/v10.13.0/lib/node_modules/ramda-repl/node_modules/ramda/src/internal/_curry3.js:35:16)
λ
我在 Ramda repl 中创建了一个代码片段:ramda-reply code snippet
你非常接近,你只是调换了 reducer 函数中的两个参数。而不是这个:
let rp = (pair, msg) => { return R.replace(pair.Key, pair.Value, msg); }
这样做:
let rp = (msg, pair) => { return R.replace(pair.Key, pair.Value, msg); }
const place_holders = "GREETINGS-{year}-{mm-month}-{dd-day} - HELLO WORLD";
let fields = ['{year}', '{mm-month}', '{dd-day}'];
let vals = ['2016', '06', '23'];
let tr = (k, v) => { return { Key: k, Value: v } }
let pairs = R.zipWith(tr, fields, vals);
let rp = (msg, pair) => { return R.replace(pair.Key, pair.Value, msg);}
console.log(R.reduce(rp, place_holders, pairs))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
正如 Nicholas Tower 指出的那样,这个错误是一个简单的换位。我的版本是将命令式代码包装在一个函数中,所以我可能会这样写:
const fillIn = (fields, place_holders, vals) => reduce(
(str, {Key, Val}) => replace(Key, Val, str),
place_holders,
zipWith((Key, Val) => ({Key, Val}), fields, vals)
)
const place_holders = "GREETINGS-{year}-{mm-month}-{dd-day} - HELLO WORLD";
let fields = ['{year}', '{mm-month}', '{dd-day}'];
let vals = ['2016', '06', '23'];
console.log(fillIn(fields, place_holders, vals))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script>
const {reduce, replace, zipWith} = R
</script>
如果我想部分应用字段(可能还有占位符),我也可以将其包装在 curry
中。
更新:您可能还想考虑不同的数据结构。使用两个数组来存储基于共享索引的成对值通常很脆弱。此结构以更稳健的方式保存相同的信息:
{year: '2016', 'mm-month': '06', 'dd-day': '23'}
使用它还可以让您使用正则表达式更动态地处理占位符:
const fillIn = (placeHolder, context) => placeHolder.replace(
/\{([^}]+)\}/g,
(s, key) => key in context ? context[key] : `{${key}}`
)
const context = {year: '2016', 'mm-month': '06', 'dd-day': '23'}
console.log(fillIn("GREETINGS-{year}-{mm-month}-{dd-day} - HELLO WORLD", context))
console.log(fillIn("GREETINGS-{foobar}-{mm-month}-{dd-day} - HELLO WORLD", context))
这有一个缺点。如果您在字符串中嵌套了大括号,这将失败。我实际上会使用更像内置字符串模板的模板,"GREETINGS-${year}-${mm-month}-${dd-day} - HELLO WORLD"
以避免这个问题,并使它们更好地脱颖而出。额外的 $
也必须添加到正则表达式中,但这很简单:/$\{([^}]+)\}/g
.
这个技巧可能对你没有帮助。如果这些数据结构来自外部系统,那么您就会陷入困境。但是,如果您可以控制它们,请考虑将其视为您现有版本的一个可能更灵活、更强大的版本。
给定一个初始消息字符串(实际上就像一个格式字符串),并包含随后要填充的占位符。
例如我们的初始消息是:
"GREETINGS-{year}-{mm-month}-{dd-day} - HELLO WORLD"
其中有 3 个占位符,{year},{mm-month }, {dd-day}
我想将其翻译成:
"GREETINGS-2016-06-23 - HELLO WORLD"
假设我们有一个对象数组如下:
[{
"Key": "{year}",
"Value": "2016"
}, {
"Key": "{mm-month}",
"Value": "06"
}, {
"Key": "{dd-day}",
"Value": "23"
}]
每个对象都有一个Key对应消息中的占位符字符串,以及用来替换占位符的Value。
我正在使用 R.reduce 函数,因为我们有一个值集合(具有 Key Value 属性的对象列表、字符串替换转换器函数 (tr) 和初始累加器是原始占位符字符串.
变换函数tr定义为:
let tr = (k, v) => { return { Key: k, Value: v } }
执行文本替换的rp函数定义为:
let rp = (pair, msg) => { return R.replace(pair.Key, pair.Value, msg); }
所以期望的效果是迭代列表,用字段值替换字段名称,在每次迭代中,return 部分填充的字符串,直到最后你有一个完全填充的字符串,没有占位符剩余。
我将 R.reduce 与 R.add 一起使用来模拟我的解决方案,即:
R.reduce(R.add, 0, [1,2,3,4,5]);
这对我来说似乎符合相同的模式,除非我弄错了。
这是 R.reduce 的调用,它没有按预期工作:
R.reduce(rp, place_holders, pairs)
λ R.reduce(rp, place_holders, pairs);
TypeError: str.replace is not a function
at replace (/Users/devuser/.nvm/versions/node/v10.13.0/lib/node_modules/ramda-repl/node_modules/ramda/src/replace.js:25:14)
at Object.f3 [as replace] (/Users/devuser/.nvm/versions/node/v10.13.0/lib/node_modules/ramda-repl/node_modules/ramda/src/internal/_curry3.js:35:16)
at XWrap.rp [as f] (repl:2:36)
at XWrap.module.exports.XWrap.@@transducer/step (/Users/devuser/.nvm/versions/node/v10.13.0/lib/node_modules/ramda-repl/node_modules/ramda/src/internal/_xwrap.js:10:17)
at _arrayReduce (/Users/devuser/.nvm/versions/node/v10.13.0/lib/node_modules/ramda-repl/node_modules/ramda/src/internal/_reduce.js:11:36)
at _reduce (/Users/devuser/.nvm/versions/node/v10.13.0/lib/node_modules/ramda-repl/node_modules/ramda/src/internal/_reduce.js:44:14)
at Object.f3 [as reduce] (/Users/devuser/.nvm/versions/node/v10.13.0/lib/node_modules/ramda-repl/node_modules/ramda/src/internal/_curry3.js:35:16)
λ
我在 Ramda repl 中创建了一个代码片段:ramda-reply code snippet
你非常接近,你只是调换了 reducer 函数中的两个参数。而不是这个:
let rp = (pair, msg) => { return R.replace(pair.Key, pair.Value, msg); }
这样做:
let rp = (msg, pair) => { return R.replace(pair.Key, pair.Value, msg); }
const place_holders = "GREETINGS-{year}-{mm-month}-{dd-day} - HELLO WORLD";
let fields = ['{year}', '{mm-month}', '{dd-day}'];
let vals = ['2016', '06', '23'];
let tr = (k, v) => { return { Key: k, Value: v } }
let pairs = R.zipWith(tr, fields, vals);
let rp = (msg, pair) => { return R.replace(pair.Key, pair.Value, msg);}
console.log(R.reduce(rp, place_holders, pairs))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>
正如 Nicholas Tower 指出的那样,这个错误是一个简单的换位。我的版本是将命令式代码包装在一个函数中,所以我可能会这样写:
const fillIn = (fields, place_holders, vals) => reduce(
(str, {Key, Val}) => replace(Key, Val, str),
place_holders,
zipWith((Key, Val) => ({Key, Val}), fields, vals)
)
const place_holders = "GREETINGS-{year}-{mm-month}-{dd-day} - HELLO WORLD";
let fields = ['{year}', '{mm-month}', '{dd-day}'];
let vals = ['2016', '06', '23'];
console.log(fillIn(fields, place_holders, vals))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js"></script>
<script>
const {reduce, replace, zipWith} = R
</script>
如果我想部分应用字段(可能还有占位符),我也可以将其包装在 curry
中。
更新:您可能还想考虑不同的数据结构。使用两个数组来存储基于共享索引的成对值通常很脆弱。此结构以更稳健的方式保存相同的信息:
{year: '2016', 'mm-month': '06', 'dd-day': '23'}
使用它还可以让您使用正则表达式更动态地处理占位符:
const fillIn = (placeHolder, context) => placeHolder.replace(
/\{([^}]+)\}/g,
(s, key) => key in context ? context[key] : `{${key}}`
)
const context = {year: '2016', 'mm-month': '06', 'dd-day': '23'}
console.log(fillIn("GREETINGS-{year}-{mm-month}-{dd-day} - HELLO WORLD", context))
console.log(fillIn("GREETINGS-{foobar}-{mm-month}-{dd-day} - HELLO WORLD", context))
这有一个缺点。如果您在字符串中嵌套了大括号,这将失败。我实际上会使用更像内置字符串模板的模板,"GREETINGS-${year}-${mm-month}-${dd-day} - HELLO WORLD"
以避免这个问题,并使它们更好地脱颖而出。额外的 $
也必须添加到正则表达式中,但这很简单:/$\{([^}]+)\}/g
.
这个技巧可能对你没有帮助。如果这些数据结构来自外部系统,那么您就会陷入困境。但是,如果您可以控制它们,请考虑将其视为您现有版本的一个可能更灵活、更强大的版本。