使用递归、Ramda.js 和无点样式重构 String 的 getPermutations()
Refactoring getPermutations() of a String using recursion, Ramda.js and a point-free style
我一直在尝试使用 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('', {});
你的解决方案似乎有几个问题,恐怕我没有时间去追究它们。 (我首先看到的是您使用 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 上玩这个。)
我一直在尝试使用 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('', {});
你的解决方案似乎有几个问题,恐怕我没有时间去追究它们。 (我首先看到的是您使用 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 上玩这个。)