【问题标题】:Javascript Array String Word Wrap Problem --- Permutation of Strings in Order and A Given Array LengthJavascript Array String Word Wrap Problem --- 字符串的排列顺序和给定的数组长度
【发布时间】:2020-10-10 01:00:50
【问题描述】:

我需要编写一个 JS 函数,它接受 1.一个字符串数组和 2.一个新数组长度,并在一个新数组中返回每个可能的字符串分组(按顺序)。

这将有助于解决一系列设计的文本自动换行问题。这是一个重要的细节,因为我不需要集合的每一个排列,唯一正确的解决方案将是正确的顺序或顺序,并且连接到同一数组元素的单词将由一个空格分隔。我一直在研究递归解决方案,但没有运气。

例如

everyPermutation([A,B,C,D,E], 4);

function everyPermutation(arr, length) {
...
}

会回来

[
  ['A B', 'C', 'D', 'E'],
  ['A', 'B C', 'D', 'E'],
  ['A', 'B', 'C D', 'E'],
  ['A', 'B', 'C', 'D E']
]

【问题讨论】:

  • everyPermutation([A,B,C,D,E], 3); 会返回什么?
  • [ ['A B C', 'D', 'E'], ['A B', 'C D', 'E'], ['A B', 'C', 'D E'], ['A', 'B C D', 'E'], ['A', 'B C', 'D E'], ['A', 'B', 'C D E'] ]
  • edit问题包含您尝试的代码
  • 递归解决方案并不太难,因此帮助您解决问题会更有意义,而不是仅仅发布一个不同的解决方案。

标签: javascript arrays recursion word-wrap


【解决方案1】:

这是一个递归实现。在每个递归级别,您迭代第一个块的可能性。递归调用是为了在删除该块的情况下产生所有可能性,并且块计数少一:

function partitions(arr, length) {
  if (length === arr.length) return [arr]; // shortcut
  if (length === 1) return [[arr.join(" ")]]; // base case
  let results = [];
  for (let firstlen = arr.length - length + 1; firstlen > 0; firstlen--) {
    let prefix = arr.slice(0, firstlen).join(" ");
    results.push(...partitions(arr.slice(firstlen), length - 1)
                    .map(result => [prefix, ...result]));
  }
  return results;
}


// Example from question
console.log(partitions(["A","B","C","D","E"], 4));
// Example from comments
console.log(partitions(["A","B","C","D","E"], 3));

【讨论】:

  • @Scott,确实,链接已删除。
【解决方案2】:

另一个实现,用我更喜欢的表达式而不是语句的风格编写,可能如下所示:

const slicedCombos = (n, xs) => 
  n == xs.length
    ?  [xs.map (x => [x])]
  : [... Array (xs .length)] .map ((_, n) => xs .slice (0, xs .length - n)) .flatMap (
      pf => slicedCombos (n - 1, xs .slice (pf .length)) .map (perm => [pf, ...perm])
    )
    
const partitions = (n, xs) =>
    slicedCombos (n, xs) .map (xss => xss .map (xs => xs .join(' ')))


console .log (partitions (4, ['A', 'B', 'C', 'D', 'E']))
console .log (partitions (3, ['A', 'B', 'C', 'D', 'E']))
.as-console-wrapper {max-height: 100% !important; top: 0}

这将切片和切块原始数组的问题与格式化输出的问题分开。前者似乎更有可能被重复使用。

在实践中,我可能会提取一个帮助函数来列出数组的前缀,因为我认为它可以重复使用。看起来像这样:

const prefixes = (xs) =>
  [... Array (xs .length)] .map ((_, n) => xs .slice (0, n + 1))  

const slicedCombos = (n, xs) => 
  n == xs.length
    ?  [xs.map (x => [x])]
  : prefixes (xs) .reverse() .flatMap (
      pfx => slicedCombos (n - 1, xs .slice (pfx .length)) .map (perm => [pfx, ...perm])
    )

附加的reverse 是按所述对这些结果进行排序。如果顺序无关紧要,我们可以跳过它。

我没有将主函数或可重用的辅助函数命名为“everyPermutation”,因为这有点误导。 “排列”意味着不同的东西。虽然我选择了“分区”,但这有点太笼统了,更好的名字会很有用。

【讨论】:

    猜你喜欢
    • 2021-03-16
    • 2019-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-05
    相关资源
    最近更新 更多