关于在 2D 数组中移动行和列:在 2D 数组中移动行和列 – Javascript

Shifting rows and columns in 2D arrays - Javascript

我有这样的情况:

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

我正在尝试创建一个移动一行或一列的函数,因此结果将是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
shiftRow(array, 1)

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

shiftColumn(array,1)

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

我希望第一个数字是最后一个数字,然后在任何情况下从那里继续。我已经尝试了几个嵌套的 for 循环,但我很想弄清楚这一点。请记住,我只编码了几个月。

这是我目前所拥有的。它最后给了我一个 undefined 错误,并且它以错误的方式移动它。

1
2
3
4
5
6
7
8
9
function shiftRow(arr) {
  var temp = arr
  for(var i = 0; i < temp.length; i++) {
    for(var j = 0; j < temp[i].length; j++) {
      temp[i][j] = temp[i][j+1]
    }
  }
  return temp;
}


前面的答案看起来不错,但是在处理数组索引时缺少一个主要的东西;验证检查。

您不想尝试访问不存在的数组索引。因此,我创建了一个小类来根据需要移动您的数组,并进行验证。如果行或列索引无效,这将抛出 Error

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
class ArrayShifter {
    static showArray(array) {
        // console.log("Array :", array);
        console.log('------');
        for (const [index, elem] of array.entries()) {
            console.log(''+elem);
        }
    }

    static validateRowIndex(array, rowIndex) {
        if (!isArray(array) || !isInt(rowIndex) || rowIndex <= 0 || rowIndex > array.length) {
            throw new Error('The row index is wrong');
        }
    }

    static validateColumnIndex(array, columnIndex) {
        if (!isArray(array) || !isInt(columnIndex) || columnIndex <= 0 || columnIndex > array[0].length) {
            throw new Error('The column index is wrong');
        }
    }

    static shiftRow(array, rowIndex) {
        ArrayShifter.validateRowIndex(array, rowIndex);
        array[rowIndex - 1].unshift(array[rowIndex - 1].pop());

        return array;
    }

    static shiftColumn(array, columnIndex) {
        ArrayShifter.validateColumnIndex(array, columnIndex);
        let prev = array[array.length - 1][columnIndex - 1];

        for (const elem of array) {
            let tmp = elem[columnIndex - 1];
            elem[columnIndex - 1] = prev;
            prev = tmp;
        }

        return array;
    }
}

let sourceArray1 = [
    [1,2,3],
    [4,5,6],
    [7,8,9],
];
let sourceArray2 = [
    [1,2,3],
    [4,5,6],
    [7,8,9],
];
let controlArrayShiftRow = [
    [3,1,2],
    [4,5,6],
    [7,8,9],
];
let controlArrayColumnRow = [
    [7,2,3],
    [1,5,6],
    [4,8,9],
];

// arrayShifter.showArray(sourceArray1);
console.log(`Shift row test is ${areArraysEqual(controlArrayShiftRow, ArrayShifter.shiftRow(sourceArray1, 1))}.`);

// arrayShifter.showArray(sourceArray2);
console.log(`Shift column test is ${areArraysEqual(controlArrayColumnRow, ArrayShifter.shiftColumn(sourceArray2, 1))}.`);




//-------------------- Unimportant js functions --------------------
function isArray(arr) {
    if (Object.prototype.toString.call([]) === '[object Array]') { //Make sure an array has a class attribute of [object Array]
        //Test passed, now check if is an Array
        return Array.isArray(arr) || (typeof arr === 'object' && Object.prototype.toString.call(arr) === '[object Array]');
    }
    else {
        throw new Exception('toString message changed for Object Array'); //Make sure the 'toString' output won't change in the futur (cf. http://stackoverflow.com/a/8365215)
    }
}
function isInt(n) {
    return typeof n === 'number' && parseFloat(n) === parseInt(n, 10) && !isNaN(n);
}
function areArraysEqual(a1, a2) {
    return JSON.stringify(a1) == JSON.stringify(a2);
}

工作代码可以在这个codepen中看到。


鉴于这个问题:

高效地转置 javascript 数组

如果要实现shiftCol

,只实现shiftRow并前后转置就足够了

1
2
3
4
5
6
7
8
9
10
11
12
function shiftRow(array,n)
{
  let retVal=[[]];
  for(i=0;i<array.length;i++)
  {
    if (i==n)
      retVal[i]= array[i].slice(1,array.length).concat(array[i][0]);
    else
      retVal[i]=array[i];
  }
  return retVal;
}

首先,您必须传递两个参数:数组和要移动的行/列。请记住,数组是从零开始的,而不是 1。所以在你的例子中,如果你想删除第一行,你需要传递 0,而不是 1。

其次,由于要将最后一个元素放在最前面,并将其他元素向下推,因此对于 shiftRow,您需要从后向前循环。这是一个解决方案。随时改进它。

1
2
3
4
5
6
7
8
9
10
function shiftRow(arr, row) {
  var temp = arr[row];
  var j=temp.length-1;
  var x=temp[j];
  for(var i = j; i > 0; i--) {
    temp[i]=temp[i-1];
  }
  temp[0]=x;
  arr[row]=temp;
}

如您所见,它仅适用于您要移动的行,并且从末尾开始,一直到前面。在循环之前,我保存最后一个元素(将被覆盖)并将其放在循环末尾的第一个插槽中。


对于行移位,您可以使用 Array#unshiftArray#pop 方法。对于移动列,请使用带有临时变量的 Array#forEach 方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
var array = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
  ],
  array1 = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
  ]

function shiftRow(arr, row) {
  arr[row - 1].unshift(arr[row - 1].pop());
  return arr;
}

function shiftCol(arr, col) {
  var prev = arr[arr.length - 1][col-1];
  arr.forEach(function(v) {
    var t = v[col - 1];
    v[col - 1] = prev;
    prev = t;
  })
  return arr;
}

console.log(shiftRow(array, 1))
console.log(shiftCol(array1, 1))