Функциональная / декларативная версия JavaScript для цикла (с этим примером)? - PullRequest
1 голос
/ 22 сентября 2019

Имея этот код

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 function

Так есть ли способ написать это более декларативным способом без изменения логики?

Ответы [ 4 ]

3 голосов
/ 23 сентября 2019

Для меня сладость заключается в использовании некоторых утилит, которые вы можете получить из lodash, ramda или любой другой слегка «функциональной» библиотеки, но с сохранением логики [ a, f(b, c, d, e) ] в обычной функции стрелки.(может быть личным предпочтением)

Необходимые шаги:

  • Разделить строку на один массив строк (я использую split("&"))
  • Разделитьмассив строк в массив массивов из 5 строк (chunk(5))
  • вызов flatMap для внешнего массива
  • Сопоставление внутренних массивов с использованием ([ head, ...tail]) => [ head, f(...tail) ], где fваша "волшебная" функция

// 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));
1 голос
/ 23 сентября 2019

Как-то так может помочь, если вам нравится 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>
1 голос
/ 22 сентября 2019

Если вам нравится декларативный / функциональный стиль, почему бы не попробовать 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>
1 голос
/ 22 сентября 2019

Вы всегда можете перейти к рекурсивной функции для обхода списков:

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 для ее результата.

...