我使用错误的Ramda函数,R.reduce似乎没有工作

问题描述 投票:1回答:2

给定一个初始消息字符串(实际上它的作用类似于格式字符串),并包含随后要填充的占位符。

例如,我们的初始信息是:

“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函数,因为我们有一个值集合(具有键值属性的对象列表,字符串替换器变换器函数(tr),并且初始累加器是原始占位符字符串。

转换函数tr定义为:

let tr =(k,v)=> {return {Key:k,Value:v}}

并且执行文本替换的rp函数定义为:

let rp =(pair,msg)=> {return R.replace(pair.Key,pair.Value,msg); }

因此,期望的效果是迭代列表,用字段值替换字段名称,在每次迭代时,返回部分弹出的字符串,直到最后您有一个完全填充的字符串,没有剩余的占位符。

我使用R.add和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

javascript functional-programming ramda.js
2个回答
2
投票

你非常接近,你只是在你的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>

3
投票

正如尼古拉斯塔指出的那样,这个错误是一个简单的换位。我的版本是将命令式代码包装在一个函数中,所以我可能会写这样的东西:

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

这种技术可能对你没有帮助。如果这些数据结构来自外部系统,那么你就会陷入困境。但是如果你掌控它们,那么可以考虑一下这个你可能已经得到的更灵活,更强大的版本。

© www.soinside.com 2019 - 2024. All rights reserved.