简体   繁体   English

Javascript Array String Word Wrap Problem ---按顺序排列字符串和给定数组长度

[英]Javascript Array String Word Wrap Problem --- Permutation of Strings in Order and A Given Array Length

I need to write a JS function which takes 1.an array of strings and 2.a new array length and returns every possible grouping of the strings (in order) in a new array.我需要编写一个 JS 函数,它接受 1.一个字符串数组和 2.一个新数组长度,并在新数组中返回每个可能的字符串分组(按顺序)。

This will help solve a text word wrap problem for a series of designs.这将有助于解决一系列设计的文本自动换行问题。 That is an important detail since I do not need every single permutation of the set, the only correct solutions will be in correct order or sequence and words joined to the same array element will be separated by a single space.这是一个重要的细节,因为我不需要集合的每一个排列,唯一正确的解决方案是按照正确的顺序或顺序,并且连接到同一数组元素的单词将被一个空格分隔。 I have been working on a recursive solution but have not had any luck so for.我一直在研究递归解决方案,但一直没有运气。

For example例如

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

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

would return会回来

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

Here is a recursive implementation.这是一个递归实现。 At each level of recursion you iterate the possibilities for the first chunk.在递归的每个级别,您迭代第一个块的可能性。 The recursive call is for producing all the possibilities with that chunk removed, and with a chunk count that is one less:递归调用是为了产生删除该块的所有可能性,并且块计数减少一:

 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));

Another implementation, written in the style I prefer of expressions over statements, might look like this:另一个实现,以我更喜欢的表达式而不是语句的风格编写,可能如下所示:

 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}

This separates the problem of slicing and dicing the original array from that of formatting the output.这将切片和切块原始数组的问题与格式化输出的问题分开。 The former seems more likely to be reusable.前者似乎更可能是可重用的。

In practice, I would probably extract a helper function for listing the prefixes of an array, again because I think it could be reusable.在实践中,我可能会提取一个帮助函数来列出数组的前缀,同样是因为我认为它可以重用。 That would look like this:那看起来像这样:

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])
    )

The additional reverse is to order these results as described.额外的reverse是按照描述对这些结果进行排序。 If the order didn't matter, we could skip it.如果顺序无关紧要,我们可以跳过它。

I don't name the main function or the reusable helper function "everyPermutation" because that's a bit misleading.我没有将主函数或可重用的辅助函数命名为“everyPermutation”,因为这有点误导。 "permutations" means something different. “排列”意味着不同的东西。 While I chose "partitions", that's a little too generic, and a better name would be useful.虽然我选择了“分区”,但这有点太笼统了,一个更好的名字会很有用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM