Я использую неправильную функцию Ramda, R.reduce, кажется, не работает - PullRequest
0 голосов
/ 28 февраля 2019

Учитывая начальную строку сообщения (которая фактически действует как строка формата) и содержит заполнители, которые впоследствии должны быть заполнены.

Например, наше первоначальное сообщение:

"ПОЗДРАВЛЕНИЯ- {год} - {мм-месяц} - {dd-day} - HELLO WORLD"

, где есть 3 места, {год}, {мм-месяц} , {дд-день}

и Iхотелось бы перевести это на:

"GREETINGS-2016-06-23 - HELLO WORLD"

Учитывая, что у нас есть массив объектов следующим образом:

[{
  "Key": "{year}",
  "Value": "2016"
}, {
  "Key": "{mm-month}",
  "Value": "06"
}, {
  "Key": "{dd-day}",
  "Value": "23"
}]

Каждый объект имеет ключ, соответствующий строке заполнителя внутри сообщения, и значение, которое используется для замены заполнителя.

Я использую функцию 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);}

Таким образом, желаемый эффект состоит в том, чтобы повторять список, заменяя имя поля значением поля, на каждой итерации возвращать частично заполненную строку до тех пор, пока в конце не получится полностью заполненная строка без места.осталось держателей.

Я смоделировал свое решение на использовании R.reduce с R.add, то есть:

R.reduce (R.add, 0, [1,2,3,4,5]);

, что, как мне кажется, соответствует тому же шаблону, если только я не ошибаюсь.

Это вызов R.reduce, который нене работает должным образом:

R.reduce (rp, place_holder, pair)

λ 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)
λ 

Я создал фрагмент кода в repl Ramda по адресу: %20%7B%20return%20%7B%20Key%3A%20k%2C%20Value%3A%20v%20%7D%20%7D%0A%0A%2F%2F%20pairs%20contains%20this%20list%20of%20objects%3A%0A%2F%2F%20%5B%7B%0A%2F%2F%20%20%20"Key"%3A%20"%7Byear%7D"%2C%0A%2F%2F%20%20%20"Value"%3A%20"2016"%0A%2F%2F%20%7D%2C%20%7B%0A%2F%2F%20%20%20"Key"%3A%20"%7Bmm-month%7D"%2C%0A%2F%2F%20%20%20"Value"%3A%20"06"%0A%2F%2F%20%7D%2C%20%7B%0A%2F%2F%20%20%20"Key"%3A%20"%7Bdd-day%7D"%2C%0A%2F%2F%20%20%20"Value"%3A%20"23"%0A%2F%2F%20%7D%5D%0A%2F%2F%0Alet%20pairs%20%3D%20R.zipWith%28tr%2C%20fields%2C%20vals%29%3B%0A%0Alet%20rp%20%3D%20%28pair%2C%20msg%29%20%3D>%20%7B%20return%20R.replace%28pair.Key%2C%20pair.Value%2C%20msg%29%3B%20%7D%0A%0Arp%28pairs%5B0%5D%2C%20place_holders%29%0A%0A%2F%2F%20-----------------%0A%2F%2F%20The%20following%20line%20...%0A%2F%2F%0A%2F%2F%20rp%28pairs%5B0%5D%2C%20place_holders%29%0A%2F%2F%0A%2F%2F%20does%20what%20is%20required%20and%20returns%20the%20string%3A%0A%2F%2F%20%0A%2F%2F%20"GREETINGS-2016-%7Bmm-month%7D-%7Bdd-day%7D%20-%20HELLO%20WORLD"%0A%2F%2F%20%28pair%5B0%5D%20equates%20to%20%7B%20"Key"%3A%20"%7Byear%7D"%2C%20"Value"%3A%20"2016"%20%7D%20%29%0A%2F%2F%0A%2F%2F%20ie%20what%20its%20doing%20is%20replacing%20field%20in%20the%20string%20with%20the%20corresponding%0A%2F%2F%20field%20value%20%28ie%20field%5B0%5D%20in%20the%20msg%20is%20replaced%20by%20vals%5B0%5D%29%0A%2F%2F%0A%2F%2F%20Now%20I%20would%20like%20to%20use%20the%20reduce%20function%20so%20that%20we%20can%20iterate%20over%20all%20of%0A%2F%2F%20objects%20in%20the%20pair%20collection%20so%20that%20at%20the%20end%20the%20final%20message%20returned%0A%2F%2F%20does%20not%20contain%20the%20field%20names%3B%20they%20have%20all%20been%20replaced%20by%20corresponding%20field%0A%2F%2F%20values%2C%20ie%3A%0A%2F%2F%0A%2F%2F%20"GREETINGS-2016-06-23%20-%20HELLO%20WORLD"%0A%2F%2F%20-----------------%0A%2F%2F%0A%2F%2F%20So%20using%20the%20reduce%20function%2C%0A%2F%2F%20-%20the%20collection%20to%20be%20iterated%20over%20is%20%27pairs%27%0A%2F%2F%20-%20the%20initial%20accumulator%20is%20place_holders%20string%20containing%20the%20field%20names%0A%2F%2F%0A%2F%2F%20But%20invocation%20of%20%27R.reduce%28rp%2C%20place_holders%2C%20pairs%29%27%20results%20in%20an%20error%20message%0A%2F%2F%20%27r.replace%20is%20not%20a%20function%27%0AR.reduce%28rp%2C%20place_holders%2C%20pairs%29%0A%0A%2F%2F%20So%20either%20I%27m%20invoking%20reduce%20incorrectly%20or%20R.reduce%20is%20the%20wrong%20function%20for%20this%0A%2F%2F%20requirement.%0A%2F%2F%0A%0A%0A%0A" rel="nofollow noreferrer"> фрагмент кода ответа ramda

Ответы [ 2 ]

0 голосов
/ 28 февраля 2019

Как указала Николас Тауэр, эта ошибка была простым переносом.Моя версия заключалась бы в том, чтобы обернуть этот императивный код внутри функции, чтобы я мог написать что-то вроде этого:

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.

Эта техника может вам не помочь.Если эти структуры данных поступают из внешней системы, то вы застряли.Но если вы контролируете их, подумайте, что это, возможно, более гибкая и надежная версия того, что вы уже получили.

0 голосов
/ 28 февраля 2019

Вы очень близки, вы просто перенесли два аргумента в свою функцию-редуктор.Вместо этого:

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>
...