首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >循环直到..。拉姆达

循环直到..。拉姆达
EN

Stack Overflow用户
提问于 2018-03-28 19:46:09
回答 2查看 2.7K关注 0票数 3

我试图用Ramda重构几段代码,我想知道,在Ramda/中解决以下代码的好方法是什么?

代码语言:javascript
复制
let arrayOfSomething = initArray();

for(let i = 0; SOME_INDEX_CONDITION(i)|| SOME_CONDITION(arrayOfSomething); i++) {
    const value = operation(arrayOfSomething);
    const nextValue = anotherOperation(value);

   arrayOfSomething = clone(nextValue)
}

因此,基本上,我想在arrayOfSomething上迭代和应用相同的管道/操作组合,直到满足其中一个条件。重要的是给我最后一个值(nextValue)作为对forLoop组合的反馈。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-03-28 20:19:40

我不知道这是否能满足你的需要,但兰达的until可能就是你所需要的:

代码语言:javascript
复制
const operation = ({val, ctr}) => ({val: val % 2 ? (3 * val + 1) : (val / 2), ctr: ctr + 1})

const indexCondition = ({ctr}) => ctr > 100
const valCondition = ({val}) =>  val === 1
const condition = R.either(indexCondition, valCondition)

const check = R.until(condition, operation)

const collatz = n => check({ctr: 0, val: n})

console.log(collatz(12)) 
// 12 -> 6 -> 3 -> 10 -> 5 -> 16 -> 8 -> 4 -> 2 -> 1 //=> {"ctr": 9, "val": 1}
console.log(collatz(5)) 
// 5 -> 16 -> 8 -> 4 -> 2 -> 1 //=> {"ctr": 5, "val": 1}
console.log(collatz(27)) 
//27 -> 82 -> 41 -> 124 -> 62 -> .... //=> {"ctr": 101, "val": 160}
代码语言:javascript
复制
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.js"></script>

票数 5
EN

Stack Overflow用户

发布于 2018-03-28 20:20:07

看起来你在寻找一个反向折叠,或unfold

大多数人都熟悉reduce:它使用一个值集合并将其还原为单个值-- unfold正好相反:它需要一个值,并将其展开为一个值集合。

如果库中已经存在类似的函数,熟悉Ramda的其他人可以发表评论。

代码语言:javascript
复制
const unfold = (f, init) =>
  f ( (x, next) => [ x, ...unfold (f, next) ]
    , () => []
    , init
    )

const nextLetter = c =>
  String.fromCharCode (c.charCodeAt (0) + 1)

const alphabet =
  unfold
    ( (next, done, c) =>
        c > 'z'
          ? done ()
          : next (c, nextLetter (c))
    , 'a'
    )

console.log (alphabet)
// [ a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z ]

unfold非常强大

代码语言:javascript
复制
const fib = (n = 0) =>
  unfold
    ( (next, done, [ n, a, b ]) =>
        n < 0
          ? done ()
          : next (a, [ n - 1, b, a + b ])
    , [ n, 0, 1 ]
    )

console.log (fib (20))
// [ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765 ]

我们可以使用iterateUntil实现您的unfold

代码语言:javascript
复制
const unfold = (f, init) =>
  f ( (x, acc) => [ x, ...unfold (f, acc) ]
    , () => []
    , init
    )
    
const iterateUntil = (f, init) =>
  unfold
    ( (next, done, [ arr, i ]) =>
        i >= arr.length || f (arr [i], i, arr)
          ? done ()
          : next (arr [i], [ arr, i + 1 ])
    , [ init, 0 ]
    )
  
const data =
  [ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i' ]
  
console.log (iterateUntil ((x, i) => i > 3, data))
// [ 'a', 'b', 'c', 'd' ]

console.log (iterateUntil ((x, i) => x === 'd', data))
// [ 'a', 'b', 'c', 'd' ]

我们可以使用asyncawait轻松地支持异步。下面我们使用asyncUnfold执行递归的db查找,从单个节点id 0开始。

  • db.getChildren接受节点id,并仅返回节点的直接子节点
  • traverse接受一个节点id,它递归地获取所有的后代子级(深度优先)。

代码语言:javascript
复制
const asyncUnfold = async (f, init) =>
  f ( async (x, acc) => [ x, ...await asyncUnfold (f, acc) ]
    , async () => []
    , init
    )

// demo async function
const Db =
  { getChildren : (id) =>
      new Promise (r => setTimeout (r, 100, data [id] || []))
  }

const Empty =
  Symbol ()

const traverse = (id) =>
  asyncUnfold
    ( async (next, done, [ id = Empty, ...rest ]) =>
        id === Empty
          ? done ()
          : next (id, [ ...await Db.getChildren (id), ...rest ])
    , [ id ]
    )
    
const data =
  { 0 : [ 1, 2, 3 ]
  , 1 : [ 11, 12, 13 ]
  , 2 : [ 21, 22, 23 ]
  , 3 : [ 31, 32, 33 ]
  , 11 : [ 111, 112, 113 ]
  , 33 : [ 333 ]
  , 333 : [ 3333 ]
  }

traverse (0) .then (console.log, console.error)
// => Promise
// ~2 seconds later
// [ 0, 1, 11, 111, 112, 113, 12, 13, 2, 21, 22, 23, 3, 31, 32, 33, 333, 3333 ]

适合unfold的其他程序

  • “从页面URL /开始,抓取所有子代页”
  • 从搜索"foo"和页面1开始,从所有页面收集结果
  • 从用户Alice开始,给我看看她的朋友和她所有朋友的朋友
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49542944

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档