1

有这个代码

const myMagic = (one, two, three, four) => `this is ${one} and ${two} and ${three} and ${four} as usual`

const txt = 'HELLO&ho&hy&hu&hq&HELLO&ho&hy&hu&hq&HELLO&ho&hy&hu&hq&HELLO&ho&hy&hu&hq&hx'
const fragments = txt.split('&')
const pieces = []

for (let i=0; i<fragments.length-1;i +=5) {
  pieces.push(fragments[i])
  pieces.push(myMagic(fragments[i+1],fragments[i+2],fragments[i+3],fragments[i+4]))
}

pieces.push(fragments[fragments.length-1])

console.log(pieces)

如何将其转换为更具声明性的版本?

代码是这样的,因为拆分采用了一个只解析一次文本的正则表达式,然后使用这些片段,我正在构建尽可能多的组件与myMagic函数

那么有没有办法在不改变逻辑的情况下以更具声明性的方式编写它?

4

4 回答 4

3

对我来说,最重要的是使用一些你可以从 lodash、ramda 或任何其他稍微“功能性”的库中获得的实用程序,但将[ a, f(b, c, d, e) ]逻辑保持在常规箭头函数中。(可能是个人喜好)

采取的步骤:

  • 将字符串拆分为一个字符串数组(我使用split("&")
  • 将字符串数组拆分为由 5 个字符串组成的数组 ( chunk(5))
  • 调用flatMap外部数组
  • ([ head, ...tail]) => [ head, f(...tail) ]使用where fis your "magic" 函数映射内部数组

// Utils
const range = s => Array.from(Array(Math.floor(s)), (_, i) => i);
const chunk = n => xs => range(xs.length / n)
  .map(i => xs.slice(i * n, i * n + n));
const split = del => str => str.split(del);
const flatMap = f => xs => xs.flatMap(f);
const pipe = (...fs) => x => fs.reduce((y, f) => f(y), x);

// App
const myMagic = (one, two, three, four) => `this is ${one} and ${two} and ${three} and ${four} as usual`

const convert = pipe(
  split("&"),
  chunk(5),
  flatMap(([ head, ...tail ]) => [ head, myMagic(...tail) ])
);

// Run it
const input = "HELLO1&ho&hy&hu&hq&HELLO2&ho&hy&hu&hq&HELLO3&ho&hy&hu&hq&HELLO4&ho&hy&hu&hq&hx";

console.log(convert(input));

于 2019-09-23T08:59:09.973 回答
1

如果你喜欢声明式/函数式风格,为什么不试试ramda.js呢?

let txt = 'HELLO A,1,2,3,4,HELLO B,a,b,c,d,HELLO C,x,y,z,w';
let fragments = txt.split(',');

const myMagic = (one, two, three, four) => `this is ${one} and ${two} and ${three} and ${four} as usual`

//

const convert = R.pipe(
    R.splitEvery(5),
    R.chain(
        R.juxt(R.pair(
            R.head,
            R.pipe(R.tail, R.apply(myMagic))
        ))
    )
)

//


console.log(convert(fragments))
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.min.js"></script>

于 2019-09-22T17:21:23.123 回答
1

您总是可以使用递归函数来遍历列表:

const myMagic = (one, two, three, four) => `this is ${one} and ${two} and ${three} and ${four} as usual`

function pieces([zero, ...rest]) {
    if (!rest.length)
        return [zero];
    const [one, two, three, four, ...more] = rest;
    return [zero, myMagic(one, two, three, four), ...pieces(more)];
}

const txt = 'HELLO&ho&hy&hu&hq&HELLO&ho&hy&hu&hq&HELLO&ho&hy&hu&hq&HELLO&ho&hy&hu&hq&hx';
console.log(pieces(txt.split('&')))

我建议在其结果上使用某种chunk(5)功能。flatMap

于 2019-09-22T15:59:47.890 回答
1

如果您喜欢ramda ,这样的事情可能会有所帮助

const data = 'HELLO&ho&hy&hu&hq&HELLO&ho&hy&hu&hq&HELLO&ho&hy&hu&hq&HELLO&ho&hy&hu&hq&hx'

const toString = ([head, a, b, c, d] = []) => [
  head,
  `this is ${a} and ${b} and ${c} and ${d} as usual`,
]

const magic = R.pipe(
  R.split('&'),
  R.splitEvery(5),
  R.map(toString),
  R.unnest,
  R.init, // to remove last malformed item
);

console.log(
  'result : ',
  magic(data),
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.26.1/ramda.js" integrity="sha256-xB25ljGZ7K2VXnq087unEnoVhvTosWWtqXB4tAtZmHU=" crossorigin="anonymous"></script>

于 2019-09-23T12:37:27.113 回答