【问题标题】:Refactoring getPermutations() of a String using recursion, Ramda.js and a point-free style [duplicate]使用递归、Ramda.js 和无点样式重构字符串的 getPermutations()
【发布时间】:2016-09-13 14:03:55
【问题描述】:

我一直在尝试使用 Ramda.js 使用无点方法将我的原始解决方案重构为 getPermutations() 函数。是否有可能进一步重构它,朝向无点风格。看来我刚刚弄得更大了。另外,当我运行测试时,当前重构版本中存在一个错误:TypeError: reduce: list must be array or iterable。

原解决方案:

// getPermutations :: String -> [String]
function getPermutations(string) {
  function permute(combination, permutations, s) {
    if (!s.length) {
      return permutations[combination] = true;
    }

    for (var i = 0; i < s.length; i++) {
      permute( combination.concat(s[i])
             , permutations
             , (s.slice(0, i) + s.slice(i+1))
             );
    }
    return Object.keys(permutations);
  }

  return permute('', {}, string);
}

我尝试用 Ramda.js 重构:

var _ = require('ramda');

// permute :: String -> {String: Boolean} -> String -> [String]
var permute = _.curry(function (combination, permutations, string) {
  // callPermute :: String -> ({String: Bool} -> Char -> Int -> String) -> IO
  var callPermute = function (combination) {
    return function (acc, item, i, s) {
      return permute( _.concat(combination, item)
                    , acc
                    , _.concat(_.slice(0, i, s), _.slice(i + Infinity, s))
                    );
    };
  };

  var storeCombination = function () { 
    return permutations[combination] = true;
  };

  // should be an ifElse, incorporating compose below
  _.when(_.not(string.length), storeCombination);

  return _.compose( _.keys
                  , _.addIndex(_.reduce(callPermute(''), {}))
                  ) (string.split(''));
});

// getPermutations :: String -> [String]
var getPermutations = permute('', {});

【问题讨论】:

  • 你有什么问题?您是否只想以无点样式编写permute 函数?这非常困难。
  • @AaditMShah,这是正确的。我希望以无点风格编写permute 函数。您的反馈会有所帮助。我不确定我是否遗漏了一些简单的东西,错误地/次优地看待问题,或者递归函数是否天生就难以重构为无点风格。感谢您的反馈!
  • 我同意它通常不值得重构为无点,特别是在不求助于定点组合器的情况下很难实现无点递归。但我不同意这个问题应该作为链接问题的副本关闭,它不是关于无积分的,没有提到库,没有谈论重构现有代码,事实上,只与此共享他们都想在 JS 中使用置换函数。这不会使它们重复。

标签: javascript recursion functional-programming pointfree ramda.js


【解决方案1】:

您的解决方案似乎有几个问题,恐怕我没有时间追究它们。 (我看到的第一件事是你错误地使用了addIndex。)

但是如果你想在 Ramda 中看到一个有效的 permutation 函数,就在不久前 I wrote this

// permutations :: [a] -> [[a]]
const permutations = (tokens, subperms = [[]]) =>
  R.isEmpty(tokens) ?
    subperms :
    R.addIndex(R.chain)((token, idx) => permutations(
      R.remove(idx, 1, tokens), 
      R.map(R.append(token), subperms)
    ), tokens);

R.map(R.join(''), permutations(['A', 'B', 'C'])); 
//=> ["ABC", "ACB", "BAC", "BCA", "CAB", "CBA"]

(你可以在 Ramda REPL 上玩这个。)

【讨论】:

  • 你的解决方案不是无点的,如果那是 OP 想要的。
  • @ScottSauyet,感谢您提供有关 addIndex 的提示。我真的很困惑为什么这不起作用。即使它不是免费的,我真的在挖掘你的解决方案。听起来我可能一直在尝试一个荒谬的练习,试图让它变得毫无意义。我知道我的重构还没有完成,但我想至少在寻求帮助之前展示我的尝试。大多数递归函数是否天生就难以以无点风格编写,还是只有一些?
  • @Eric 每个函数都可以转换成无点版本。但是,这并不意味着每个功能都应该。无点函数在eta conversionfunction composition 等非常有限的情况下才有意义。在大多数其他情况下,pointful 函数更具可读性。有一个algorithm 可以将点表达式转换为无点表达式。
猜你喜欢
  • 2019-01-15
  • 2017-10-08
  • 2021-12-28
  • 2013-04-06
  • 2014-01-01
  • 2019-12-21
  • 2019-06-03
  • 2015-02-20
  • 1970-01-01
相关资源
最近更新 更多