当前位置: 首页 > 知识库问答 >
问题:

翻转或旋转一维数组

田巴英
2023-03-14

我有一个一维数组,它代表一个二维网格。行和列的数量是已知的。从“左上角”到“右下角”读取,因此第一项为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

共有3个答案

童冠玉
2023-03-14

使用一个简单的转置助手,它可以在主对角线上翻转矩阵,我们可以编写真正简单的水平翻转顺时针旋转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 ()

如果我们将mapreverse具体化为纯函数,并添加compose,它们可能会更简单:

const flipHorizontal = map (reverse)
const flipVertical = reverse
const rotate90Clockwise = compose (transpose, reverse)
const rotate90Counter = compose (reverse, transpose)

但是这些函数在二维数组上运行(从技术上讲,JS中的数组数组)我们需要在一维数组上操作的函数,就像它是一个二维数组一样,每一行的长度都是colsentries。我们可以重写简单的函数,这不会太困难。但我们也可以将它们包装在其他函数中。如果我们有一个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}
漆雕昊天
2023-03-14

下面是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
岳玉堂
2023-03-14

对于基本迭代,您可以循环行,并且在每行中循环列。

关键部分是:

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中,但是看到变量是不确定的,因此我不确定这是最好的解决方案。提前致谢。 问题答案: 在代码中添加一个模数组长度: 您还应该创建一个要复制到的新值,以免覆盖以后需要的值。