从给定数组生成增量值数组



如何从给定数组生成增量值数组

这个想法是创建一种菱形形状,其中数组一旦到达阵列的中间,其大小就会开始减小。换句话说,最长的数组将是包含数组中间值或(array.length/2 + 1)的数组

。如果元素很短以完成后半部分的数组,只需将其替换为"E"以表示空白空间,就像第二个示例一样。

example 1
var array = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p']
//the longest array in length is containing 'i' which is the value at 
array.length/2 + 1
var output = [
['a'],
['b','c'],
['d','e','f'],
['g','h','i','j'], 
['k','l','m'],
['n','o'],
['p']
]
example 2
var array = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t']
enter code here
//the longest array in length is containing 'k' which is the value at array.length/2 + 1
var output = [
['a'],
['b','c'],
['d','e','f'],
['g','h','i','j'],
['k','l','m','n','o'],
['p','q','r','s'],
['t','E','E'],
['E','E'],
['E]
]

这是我尝试过的代码:

const values = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16];
const halfLen = values.length/2 + 1;
var topArr = [];
for(let i = 0; i < values.length; i ++) {
if(i <= halfLen) {
topArr.push(values[i])
}

}
console.log(topArr)
var filTopArr = [];
for(let i = 0; i <= topArr.length; i ++) {
let prevIndex = i - 1;

if(i === 0) {
filTopArr.push(topArr[i])
}  else if(i === 1) {
filTopArr.push(topArr.slice(i, i + i + 1))
} else {
filTopArr.push(topArr.slice(i, i + i ))
}

}
console.log(filTopArr)

我的想法是将数组分成两个不同的数组,这两个数组将是大小递增

的顶部和大小递减的第二/底部。上面的代码有这个输出

[1, [2, 3], [3, 4], [4, 5, 6], [5, 6, 7, 8], [6, 7, 8, 9], [7, 8, 9], [8, 9], [9], []]

一些观察:

  • 输出中的字符串数(包括填充"E"字符串)始终是完美的正方形(1、4、9、16、25、...等)

  • 为了知道需要添加多少个"E"字符串,我们需要知道哪个是最不完美的平方,不小于输入大小。

  • 输出中最长(中间)子数组的大小是该完美正方形的平方根。

  • 子数组的数量是该数字减去 1 的两倍。

这会导致以下实现:

function diamond(array) {
// Get least perfect square that is not less than the array length 
const sqrt = Math.ceil(Math.sqrt(array.length));
const size = sqrt ** 2;
// Pad the array with "E" strings so to reach that perfect square size
const all = [...array, ..."E".repeat(size - array.length)];
const length = 2 * sqrt;
return Array.from({length}, (_, width) => {
return all.splice(0, Math.min(width, length - width));
}).slice(1); // Skip the first subarray that was produced (empty array)
}
// Demo using the two provided examples:
var array = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p'];
console.log(diamond(array));
var array = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t'];
console.log(diamond(array));

这是一个递归版本。 请注意,display仅用于演示目的。 唯一真正的工作是diamond

const diamond = (xs, [len = xs.length, up = true, n = 1] = []) => n == 0 ? [] : [
Object .assign (Array (n) .fill ('E'), xs .slice (0, n)),
...diamond (xs .slice (n), up && n * n < len  ? [len, true, n + 1] : [len, false, n - 1])
]
const display = (xss) => console .log (`${xss .map (
(xs, i) => `${' '.repeat (Math .abs ((xss .length - 1) / 2 - i) + 1)}${xs .join (' ')
}`) .join ('n')}`)

const demos = [
['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p'],
['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u'],
[1, 2, 3, 4, 5, 6, 7, 8]
]

demos .forEach (array => display (diamond (array)))
.as-console-wrapper {max-height: 100% !important; top: 0}

我们跟踪当前字符串的长度(n,默认为1),原始数组的长度(len),以及一个布尔标志来判断我们的长度是向上还是向下移动(up)。 我们增加了初始迭代的n,从输入中添加接下来的n个字符作为下一个子数组。 当n达到零时,我们返回一个空数组。 当n ** n大于或等于len时,我们将up切换为假,并从n开始减去一。 唯一的其他必要条件是用'E's 填充我们剩余的数组。 我们通过Object .assign电话来做到这一点。

如果您希望格式化输出更像数组文字形式,您可以使用此版本的display

const display = (xss) => console .log (`[n${xss .map (
(xs, i) => `${'  '.repeat (Math .abs ((xss .length - 1) / 2 - i) + 1)}['${xs .join (`','`)
}']`) .join ('n')}n]`)

要获得这样的输出:

[
['a']
['b','c']
['d','e','f']
['g','h','i','j']
['k','l','m','n','o']
['p','q','r','s']
['t','u','E']
['E','E']
['E']
]

请注意,这种递归有点霸道,有三个单独的默认递归变量。 我很可能会选择trincot的解决方案。 但有替代方案是件好事。

最新更新