我有一个一维数组,它代表一个二维网格。行和列的数量是已知的。从“左上角”到“右下角”读取,因此第一项为R1C1,最后一项为RXCY(其中X=行编号,Y=列编号;
我的目标是翻转或旋转二维数组,并返回一个新的一维数组表示转换。
我尝试了按位操作,但无法让它与行/行计数可能是奇数或偶数的事实一起工作。我也尝试了迭代方法,但在逻辑杂草中迷失了方向。
一个最简单的javascript示例:9项数组中的3^3布尔网格和占位符,用于我正在处理的三个函数:
let startingArray =
[true, false, false,
true, true, true,
false, false, false];
let rows = 3;
let cols = 3;
function flipVertical(arrayToFlip){
//Logic to replace here
let flippedArray = arrayToFlip;
return flippedArray;
}
function flipHorizontal(arrayToFlip){
//Logic to replace here
let flippedArray = arrayToFlip;
return flippedArray;
}
function rotate90Clockwise(arrayToRotate){
//Logic to replace here
let rotatedArray = arrayToRotate;
return rotatedArray ;
}
console.log(flipVertical(startingArray));
// should return
// false, false, false,
// true, true, true,
// true, false, false
console.log(flipHorizontal(startingArray));
// should return
// false, false, true,
// true, true, true,
// false, false, false
console.log(rotate90Clockwise(startingArray));
// should return
//false, true, true,
//false, true, false,
//false, true, false
使用一个简单的转置
助手,它可以在主对角线上翻转矩阵,我们可以编写真正简单的水平翻转
和顺时针旋转90
,等等:
const flipHorizontal = (xs) => xs .map (x => [...x] .reverse())
const flipVertical = (xs) => [...xs] .reverse()
const rotate90Clockwise = (xs) => transpose ([...xs] .reverse())
const rotate90Counter = (xs) => transpose (xs) . reverse ()
如果我们将map
和reverse
具体化为纯函数,并添加compose
,它们可能会更简单:
const flipHorizontal = map (reverse)
const flipVertical = reverse
const rotate90Clockwise = compose (transpose, reverse)
const rotate90Counter = compose (reverse, transpose)
但是这些函数在二维数组上运行(从技术上讲,JS中的数组数组)我们需要在一维数组上操作的函数,就像它是一个二维数组一样,每一行的长度都是cols
entries。我们可以重写简单的函数,这不会太困难。但我们也可以将它们包装在其他函数中。如果我们有一个nest
函数,它获取所需的列数并将其转换为二维网格,那么我们可以先调用nest
,然后运行flipHorizontal
,然后使用数组。原型展开
,以将它们返回到展开形式。这意味着我们的简单函数将保持简单,我们仍然可以在需要时直接使用它们。
nest
函数也很简单,利用前面讨论过的帮助程序,我们可以从平面构建fromFlat
,它获取列数和一个函数,并为您提供这些矩阵操作函数的包装版本,以便它以平面数组开始和结束,但在应用操作之前将其转换为矩阵,然后再转换回平面数组。
它可能是这样的:
const reverse = (xs) => [...xs] .reverse();
const transpose = (xs) => xs [0] .map ((_, i) => xs .map (r => r[i]))
const flatten = (xss) => xss .flat ()
const map = (fn) => (o) => Array .isArray (o)
? o .map (x => fn (x))
: Object .fromEntries (Object .entries (o) .map (([k, v]) => [k, fn (v)]))
const compose = (...fns) => (x) => [...fns] .reduceRight ((a, fn) => fn (a), x)
const nest = (c) => (xs) =>
xs .length < c ? [...xs] : [xs .slice (0, c), ...nest (c) (xs .slice (c))]
const fromFlat = (cols) => (fn) => compose (flatten, fn, nest (cols))
const flipHor = map (reverse)
const flipVert = reverse
const rotateCW = compose (transpose, reverse)
const rotateCCW = compose (reverse, transpose)
const cols = 3
const flipHorizontal = fromFlat (cols) (flipHor)
const flipVertical = fromFlat (cols) (flipVert)
const rotate90Clockwise = fromFlat (cols) (rotateCW)
const rotate90Counter = fromFlat (cols) (rotateCCW)
const display = (c) => (name) => (xs) => console .log (`${name}:\n${name.replace(/./g, '=')}=\n${nest (c) (xs) .map (xs => xs .map (x => String (x) .padEnd (5, ' ')) .join (' ')) .join ('\n')}\n\n`)
const startingArray = [true, false, false, true, true, true, false, false, false]
display (cols) ('original') (startingArray)
display (cols) ('flipHorizontal') (flipHorizontal (startingArray))
display (cols) ('flipVertical') (flipVertical (startingArray))
display (cols) ('rotate90Clockwise') (rotate90Clockwise (startingArray))
display (cols) ('rotate90Counter') (rotate90Counter (startingArray))
.as-console-wrapper {max-height: 100% !important; top: 0}
下面是flipVertical
的一个示例。基本上我创建了2个函数来将数组索引映射到col/行和col/行。我还创建了一个函数,使用将一个索引映射到另一个索引的函数来转换数组。
所以为了创建flipVertical
,我写了这样的逻辑:
在那里,我想你可以写其他函数:)
let startingArray =
[true, false, false,
true, true, true,
false, false, false];
let rows = 3;
let cols = 3;
function transformArray(originalArray, indexMapFn) {
const resultArray = originalArray.concat();
for (let i = 0; i < originalArray.length; i++) {
resultArray[i] = originalArray[indexMapFn(i)];
}
return resultArray;
}
function mapIndexToColRow(i) {
const row = Math.floor(i / cols);
const col = i % cols;
return { row, col };
}
function mapColRowToIndex(col, row) {
return row * cols + col;
}
function flipVertical(arrayToFlip){
return transformArray(arrayToFlip, (i) => {
const { row, col } = mapIndexToColRow(i);
const pivotRow = (rows-1)/2;
const distToPivot = pivotRow - row;
const newRow = pivotRow + distToPivot;
// once you get the logic you can simplify to:
// newRow = (rows - 1) - row
return mapColRowToIndex(col, newRow);
});
}
console.log(flipVertical(startingArray));
// should return
// false, false, false,
// true, true, true,
// true, false, false
对于基本迭代,您可以循环行,并且在每行中循环列。
关键部分是:
arr[r * cols + c]
从一个“重复”函数开始,该函数简单地循环遍历数字或行以及来自
let rows = 3;
let cols = 3;
并推送到一个新阵列
function duplicate(arr) {
var result = [];
for (var r = 0; r < rows; r++) {
for (var c = 0; c < cols; c++) {
result.push(arr[r * cols + c]);
}
}
return result;
}
然后,您可以操作这个基本迭代来反转行(flipVertical):
for (var r = rows - 1; r >= 0; r--) {
或反向列(水平翻转)
for (var c = cols - 1; c >= 0; c--) {
要旋转,您可以根据要旋转的方式将r*ol c
切换到c*row r
给:
let startingArray = [true, false, false,
true, true, true,
false, false, false
];
let rows = 3;
let cols = 3;
console.log(startingArray);
console.log(duplicate(startingArray));
console.log(flipVertical(startingArray));
console.log(flipHorizontal(startingArray));
console.log(rotate90Clockwise(startingArray));
function duplicate(arr) {
var result = [];
for (var r = 0; r < rows; r++) {
for (var c = 0; c < cols; c++) {
result.push(arr[r * cols + c]);
}
}
return result;
}
function flipVertical(arr) {
var result = [];
for (var r = rows - 1; r >= 0; r--) {
for (var c = 0; c < cols; c++) {
result.push(arr[r * cols + c]);
}
}
return result;
}
function flipHorizontal(arr) {
var result = [];
for (var r = 0; r < rows; r++) {
for (var c = cols - 1; c >= 0; c--) {
result.push(arr[r * cols + c]);
}
}
return result;
}
function rotate90Clockwise(arr) {
var result = [];
for (var r = 0; r < rows; r++) {
for (var c = cols - 1; c >= 0; c--) {
result.push(arr[c * rows + r]);
}
}
return result;
}
问题内容: 在一个程序中,我正在写一个旋转二维数组的需求。在寻找最佳解决方案时,我发现了这种令人印象深刻的一线功能: 我现在在程序中使用它,它按预期工作。我的问题是,我不了解它是如何工作的。 如果有人可以解释所涉及的不同功能如何实现所需的结果,我将不胜感激。 问题答案: 考虑以下二维列表: 让我们将其逐步分解: 此列表传递给使用参数unpacking,因此调用最终等效于此: 希望注释能够清楚说明其
问题内容: 我想找出悬停时如何制作 旋转或旋转的图像 。我想知道如何在以下代码上使用 CSS 模仿该功能: 问题答案: 您可以将CSS3过渡与一起使用,以 在悬停时旋转图像 。 旋转图像:
我正在构建一个应用程序,它依赖于显示从相机拍摄的许多位图图像。我希望所有图像都以90度(纵向)的方向显示,我知道如何使用每个图像提供的EXIF信息来实现这一点。在拍摄图像后立即旋转图像的位图以满足我的需要,然后将其发送到我的服务器,这对我来说是一个更好的主意,还是应该在不旋转图像的情况下将图像发送到我的服务器,然后每当我下拉图像时,使用图像附带的EXIF旋转来旋转我正在显示的图像视图?我需要一个高
本文向大家介绍C#控制图像旋转和翻转的方法,包括了C#控制图像旋转和翻转的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了C#控制图像旋转和翻转的方法。分享给大家供大家参考。具体实现方法如下: 希望本文所述对大家的C#程序设计有所帮助。
本文向大家介绍C++实现一维向量旋转算法,包括了C++实现一维向量旋转算法的使用技巧和注意事项,需要的朋友参考一下 在《编程珠玑》一书的第二章提到了n元一维向量旋转算法(又称数组循环移位算法)的五种思路,并且比较了它们在时间和空间性能上的区别和优劣。本文将就这一算法做较为深入的分析。具体如下所示: 一、问题描述 将一个n元一维向量向左旋转i个位置。例如,假设n=8,i=3,向量abcdefgh旋转
问题内容: 因此,目标是将阵列中的元素正确旋转一次。举个例子; 如果, 则将成为 这是我所拥有的: 但是,这无法说明何时大于数组的长度。我读到我应该将更大的存储在另一个Array中,但是看到变量是不确定的,因此我不确定这是最好的解决方案。提前致谢。 问题答案: 在代码中添加一个模数组长度: 您还应该创建一个要复制到的新值,以免覆盖以后需要的值。