1

To feed the data to a function correctly, I need to swap two axes in a four-dimensional array in Swift. I'd like to know how to implement or are there any useful function for this purpose.

In Python, if I use numpy.swapaxes(a, axis1, axis2), it's straightforward (https://docs.scipy.org/doc/numpy/reference/generated/numpy.swapaxes.html):

def swapaxes_from_tail_to_head(nparray):
    nparray = np.swapaxes(nparray, 2, 3)
    nparray = np.swapaxes(nparray, 1, 2)
    nparray = np.swapaxes(nparray, 0, 1)
    return nparray

Just note that if the array is two-dimensional, I can do like this:

func prettyPrintMatrix( _ matrix:[[Int]] ) {
  for array in matrix {
    print( array )
  }
}

func main() -> (){
  print( "MatrixTranspose_Demo" )
  print()

  let matrix = 
  [
    [ 1, 2, 3 ],
    [ 4, 5, 6 ],
  ]

  print( "Matrix:")
  prettyPrintMatrix( matrix )
  print()

  let transpose = transposeMatrix( matrix )

  print( "Transpose matrix:")
  prettyPrintMatrix( transpose )
  print()
}

func transposeMatrix( _ matrix:[[Int]] ) -> [[Int]] {    
  var result = [[Int]](
    repeating: [Int]( repeating: 0, count: matrix.count ), 
    count: matrix[ 0 ].count
  )

  for i in 0 ..< matrix.count {
    for k in 0 ..< matrix[ 0 ].count {
        result[ k ][ i ] = matrix[ i ][ k ]
    }
  }
  return result
}

main()
// Reference: http://www.runswiftlang.com/

If you have any ideas how to do swapaxes for four-dimentional (or more) array, please let me know. I appreciate your help.

kangaroo
  • 407
  • 4
  • 19

3 Answers3

0

The simplest way is to hard code everything like the followings:

  internal func swapaxesOfFlatArray4d<T>(originalArray: [T], axis1: Int, axis2: Int, dimensionOfArray: [Int]) -> [T] {
    assert(axis1 != axis2)
    assert(dimensionOfArray.count == 4)
    assert(axis1 < dimensionOfArray.count)
    assert(axis2 < dimensionOfArray.count)
    assert(originalArray.count == dimensionOfArray.reduce(1, *))
    assert((T.self == Float.self) || (T.self == Double.self))

    var newArray = Array<T>()

    if ((axis1 == 0 && axis2 == 1) || (axis1 == 1 && axis2 == 0)) {

      for j in 0..<dimensionOfArray[1] {
        for i in 0..<dimensionOfArray[0] {
          for k in 0..<dimensionOfArray[2] {
            for l in 0..<dimensionOfArray[3] {
              newArray.append(originalArray[i*dimensionOfArray[1]*dimensionOfArray[2]*dimensionOfArray[3] + j*dimensionOfArray[2]*dimensionOfArray[3] + k*dimensionOfArray[3] + l])
            }
          }
        }
      }

    } else if ((axis1 == 0 && axis2 == 2) || (axis1 == 2 && axis2 == 0)) {

      for k in 0..<dimensionOfArray[2] {
        for j in 0..<dimensionOfArray[1] {
          for i in 0..<dimensionOfArray[0] {
            for l in 0..<dimensionOfArray[3] {
              newArray.append(originalArray[i*dimensionOfArray[1]*dimensionOfArray[2]*dimensionOfArray[3] + j*dimensionOfArray[2]*dimensionOfArray[3] + k*dimensionOfArray[3] + l])
            }
          }
        }
      }

    } else if ((axis1 == 0 && axis2 == 3) || (axis1 == 3 && axis2 == 0)) {

      for l in 0..<dimensionOfArray[3] {
        for j in 0..<dimensionOfArray[1] {
          for k in 0..<dimensionOfArray[2] {
            for i in 0..<dimensionOfArray[0] {
              newArray.append(originalArray[i*dimensionOfArray[1]*dimensionOfArray[2]*dimensionOfArray[3] + j*dimensionOfArray[2]*dimensionOfArray[3] + k*dimensionOfArray[3] + l])
            }
          }
        }
      }

    } else if ((axis1 == 1 && axis2 == 2) || (axis1 == 2 && axis2 == 1)) {

      for i in 0..<dimensionOfArray[0] {
        for k in 0..<dimensionOfArray[2] {
          for j in 0..<dimensionOfArray[1] {
            for l in 0..<dimensionOfArray[3] {
              newArray.append(originalArray[i*dimensionOfArray[1]*dimensionOfArray[2]*dimensionOfArray[3] + j*dimensionOfArray[2]*dimensionOfArray[3] + k*dimensionOfArray[3] + l])
            }
          }
        }
      }

    } else if ((axis1 == 1 && axis2 == 3) || (axis1 == 3 && axis2 == 1)) {

      for i in 0..<dimensionOfArray[0] {
        for l in 0..<dimensionOfArray[3] {
          for k in 0..<dimensionOfArray[2] {
            for j in 0..<dimensionOfArray[1] {
              newArray.append(originalArray[i*dimensionOfArray[1]*dimensionOfArray[2]*dimensionOfArray[3] + j*dimensionOfArray[2]*dimensionOfArray[3] + k*dimensionOfArray[3] + l])
            }
          }
        }
      }

    } else if ((axis1 == 2 && axis2 == 3) || (axis1 == 3 && axis2 == 2)) {

      for i in 0..<dimensionOfArray[0] {
        for j in 0..<dimensionOfArray[1] {
          for l in 0..<dimensionOfArray[3] {
            for k in 0..<dimensionOfArray[2] {
              newArray.append(originalArray[i*dimensionOfArray[1]*dimensionOfArray[2]*dimensionOfArray[3] + j*dimensionOfArray[2]*dimensionOfArray[3] + k*dimensionOfArray[3] + l])
            }
          }
        }
      }

    } else {
      fatalError("Didn't match all the case")
    }

    return newArray
  }

To decrease the amount of the code, you can a class to change the order of for loops. Change order of for loops?

Community
  • 1
  • 1
kangaroo
  • 407
  • 4
  • 19
0

It is fairly easy to make a transpose function for a 2d matrix:

func transpose<T>(_ matrix:[[T]]) -> [[T]]
{
  return matrix.reduce([[T]]())
         {
           zip($0,$1).map{$0+[$1]} 
           + $0.dropFirst($1.count) 
           + $1.dropFirst($0.count).map{[$0]} 
         }
}

Once you have that, all other transpositions of any dimensions can be converted to a series of 2d transposes on consecutive dimensions (essentially swapping them)

let array12   = (1...4).map{ n in (1...4).map{n*10 + $0} }
let array123  = (1...4).map{ n in array12.map{ $0.map{ n*100 + $0 } } }
let array1234 = (1...4).map{ n in array123.map{ $0.map{ $0.map{ n*1000 + $0 } } } }

let array2134 = transpose(array1234)           // swap dimensions 1 and 2
let array1324 = array1234.map{transpose($0)}   // swap dimensions 2 and 3
let array1243 = array1234.map{$0.map{transpose($0)}} // swap dimensions 3 and 4

Reusing these 3 basic dimension swaps, all other combinations of the 4 dimensions are possible.

let array2143 = array2134.map{$0.map{transpose($0)}}
let array2413 = array2143.map{transpose($0)}
let array4213 = transpose(array2413)
let array4231 = array4213.map{$0.map{transpose($0)}}
let array4321 = array4231.map{transpose($0)}
// and so on ...

To help test this, I made a 4d print function for the matrix that I used in the playground:

It prints in row column order so you get dimension one as a vertical group of "blocks", dimension 2 as a column of blocks, dimension 3 is rows of each block and dimension 4 is the columns of each block:

func print4d<T>(_ matrix4d:[[[[T]]]])
{
   var lines:[String] = []
   for d1 in matrix4d
   {
      lines = []
      for (indent,d2) in d1.enumerated()
      {
         let indentWidth = indent * 80
         var lineNumber = 0
         let blankLine = "".padding(toLength:indentWidth, withPad:" ", startingAt:0)
         for d34 in d2
         {
            while lines.count <= lineNumber
            { lines.append(blankLine) }
            lines[lineNumber] = lines[lineNumber]
                                .padding(toLength:indentWidth, withPad:" ", startingAt:0)
                              + "  \(d34)" 

            lineNumber += 1
         }
         for index in lines.indices
         {
            while lines[index].contains("  ")
            { lines[index] = lines[index].replacingOccurrences(of: "  ", with: " ") }
         }             
      }
      lines.forEach{ print($0) }
      print("")
   }
}



 4d matrix :  d1, d2, d3, d4
 ===========================
 [1111, 1112, 1113, 1114] [1211, 1212, 1213, 1214] [1311, 1312, 1313, 1314] [1411, 1412, 1413, 1414]
 [1121, 1122, 1123, 1124] [1221, 1222, 1223, 1224] [1321, 1322, 1323, 1324] [1421, 1422, 1423, 1424]
 [1131, 1132, 1133, 1134] [1231, 1232, 1233, 1234] [1331, 1332, 1333, 1334] [1431, 1432, 1433, 1434]
 [1141, 1142, 1143, 1144] [1241, 1242, 1243, 1244] [1341, 1342, 1343, 1344] [1441, 1442, 1443, 1444]

 [2111, 2112, 2113, 2114] [2211, 2212, 2213, 2214] [2311, 2312, 2313, 2314] [2411, 2412, 2413, 2414]
 [2121, 2122, 2123, 2124] [2221, 2222, 2223, 2224] [2321, 2322, 2323, 2324] [2421, 2422, 2423, 2424]
 [2131, 2132, 2133, 2134] [2231, 2232, 2233, 2234] [2331, 2332, 2333, 2334] [2431, 2432, 2433, 2434]
 [2141, 2142, 2143, 2144] [2241, 2242, 2243, 2244] [2341, 2342, 2343, 2344] [2441, 2442, 2443, 2444]

 [3111, 3112, 3113, 3114] [3211, 3212, 3213, 3214] [3311, 3312, 3313, 3314] [3411, 3412, 3413, 3414]
 [3121, 3122, 3123, 3124] [3221, 3222, 3223, 3224] [3321, 3322, 3323, 3324] [3421, 3422, 3423, 3424]
 [3131, 3132, 3133, 3134] [3231, 3232, 3233, 3234] [3331, 3332, 3333, 3334] [3431, 3432, 3433, 3434]
 [3141, 3142, 3143, 3144] [3241, 3242, 3243, 3244] [3341, 3342, 3343, 3344] [3441, 3442, 3443, 3444]

 [4111, 4112, 4113, 4114] [4211, 4212, 4213, 4214] [4311, 4312, 4313, 4314] [4411, 4412, 4413, 4414]
 [4121, 4122, 4123, 4124] [4221, 4222, 4223, 4224] [4321, 4322, 4323, 4324] [4421, 4422, 4423, 4424]
 [4131, 4132, 4133, 4134] [4231, 4232, 4233, 4234] [4331, 4332, 4333, 4334] [4431, 4432, 4433, 4434]
 [4141, 4142, 4143, 4144] [4241, 4242, 4243, 4244] [4341, 4342, 4343, 4344] [4441, 4442, 4443, 4444]



 4d matrix :  d2, d1, d3, d4
 ===========================
 [1111, 1112, 1113, 1114] [2111, 2112, 2113, 2114] [3111, 3112, 3113, 3114] [4111, 4112, 4113, 4114]
 [1121, 1122, 1123, 1124] [2121, 2122, 2123, 2124] [3121, 3122, 3123, 3124] [4121, 4122, 4123, 4124]
 [1131, 1132, 1133, 1134] [2131, 2132, 2133, 2134] [3131, 3132, 3133, 3134] [4131, 4132, 4133, 4134]
 [1141, 1142, 1143, 1144] [2141, 2142, 2143, 2144] [3141, 3142, 3143, 3144] [4141, 4142, 4143, 4144]

 [1211, 1212, 1213, 1214] [2211, 2212, 2213, 2214] [3211, 3212, 3213, 3214] [4211, 4212, 4213, 4214]
 [1221, 1222, 1223, 1224] [2221, 2222, 2223, 2224] [3221, 3222, 3223, 3224] [4221, 4222, 4223, 4224]
 [1231, 1232, 1233, 1234] [2231, 2232, 2233, 2234] [3231, 3232, 3233, 3234] [4231, 4232, 4233, 4234]
 [1241, 1242, 1243, 1244] [2241, 2242, 2243, 2244] [3241, 3242, 3243, 3244] [4241, 4242, 4243, 4244]

 [1311, 1312, 1313, 1314] [2311, 2312, 2313, 2314] [3311, 3312, 3313, 3314] [4311, 4312, 4313, 4314]
 [1321, 1322, 1323, 1324] [2321, 2322, 2323, 2324] [3321, 3322, 3323, 3324] [4321, 4322, 4323, 4324]
 [1331, 1332, 1333, 1334] [2331, 2332, 2333, 2334] [3331, 3332, 3333, 3334] [4331, 4332, 4333, 4334]
 [1341, 1342, 1343, 1344] [2341, 2342, 2343, 2344] [3341, 3342, 3343, 3344] [4341, 4342, 4343, 4344]

 [1411, 1412, 1413, 1414] [2411, 2412, 2413, 2414] [3411, 3412, 3413, 3414] [4411, 4412, 4413, 4414]
 [1421, 1422, 1423, 1424] [2421, 2422, 2423, 2424] [3421, 3422, 3423, 3424] [4421, 4422, 4423, 4424]
 [1431, 1432, 1433, 1434] [2431, 2432, 2433, 2434] [3431, 3432, 3433, 3434] [4431, 4432, 4433, 4434]
 [1441, 1442, 1443, 1444] [2441, 2442, 2443, 2444] [3441, 3442, 3443, 3444] [4441, 4442, 4443, 4444]



 4d matrix :  d1, d2, d4, d3
 ===========================
 [1111, 1121, 1131, 1141] [2111, 2121, 2131, 2141] [3111, 3121, 3131, 3141] [4111, 4121, 4131, 4141]
 [1112, 1122, 1132, 1142] [2112, 2122, 2132, 2142] [3112, 3122, 3132, 3142] [4112, 4122, 4132, 4142]
 [1113, 1123, 1133, 1143] [2113, 2123, 2133, 2143] [3113, 3123, 3133, 3143] [4113, 4123, 4133, 4143]
 [1114, 1124, 1134, 1144] [2114, 2124, 2134, 2144] [3114, 3124, 3134, 3144] [4114, 4124, 4134, 4144]

 [1211, 1221, 1231, 1241] [2211, 2221, 2231, 2241] [3211, 3221, 3231, 3241] [4211, 4221, 4231, 4241]
 [1212, 1222, 1232, 1242] [2212, 2222, 2232, 2242] [3212, 3222, 3232, 3242] [4212, 4222, 4232, 4242]
 [1213, 1223, 1233, 1243] [2213, 2223, 2233, 2243] [3213, 3223, 3233, 3243] [4213, 4223, 4233, 4243]
 [1214, 1224, 1234, 1244] [2214, 2224, 2234, 2244] [3214, 3224, 3234, 3244] [4214, 4224, 4234, 4244]

 [1311, 1321, 1331, 1341] [2311, 2321, 2331, 2341] [3311, 3321, 3331, 3341] [4311, 4321, 4331, 4341]
 [1312, 1322, 1332, 1342] [2312, 2322, 2332, 2342] [3312, 3322, 3332, 3342] [4312, 4322, 4332, 4342]
 [1313, 1323, 1333, 1343] [2313, 2323, 2333, 2343] [3313, 3323, 3333, 3343] [4313, 4323, 4333, 4343]
 [1314, 1324, 1334, 1344] [2314, 2324, 2334, 2344] [3314, 3324, 3334, 3344] [4314, 4324, 4334, 4344]

 [1411, 1421, 1431, 1441] [2411, 2421, 2431, 2441] [3411, 3421, 3431, 3441] [4411, 4421, 4431, 4441]
 [1412, 1422, 1432, 1442] [2412, 2422, 2432, 2442] [3412, 3422, 3432, 3442] [4412, 4422, 4432, 4442]
 [1413, 1423, 1433, 1443] [2413, 2423, 2433, 2443] [3413, 3423, 3433, 3443] [4413, 4423, 4433, 4443]
 [1414, 1424, 1434, 1444] [2414, 2424, 2434, 2444] [3414, 3424, 3434, 3444] [4414, 4424, 4434, 4444]



 4d matrix :  d1, d3, d2, d4
 ===========================
 [1111, 1112, 1113, 1114] [1121, 1122, 1123, 1124] [1131, 1132, 1133, 1134] [1141, 1142, 1143, 1144]
 [2111, 2112, 2113, 2114] [2121, 2122, 2123, 2124] [2131, 2132, 2133, 2134] [2141, 2142, 2143, 2144]
 [3111, 3112, 3113, 3114] [3121, 3122, 3123, 3124] [3131, 3132, 3133, 3134] [3141, 3142, 3143, 3144]
 [4111, 4112, 4113, 4114] [4121, 4122, 4123, 4124] [4131, 4132, 4133, 4134] [4141, 4142, 4143, 4144]

 [1211, 1212, 1213, 1214] [1221, 1222, 1223, 1224] [1231, 1232, 1233, 1234] [1241, 1242, 1243, 1244]
 [2211, 2212, 2213, 2214] [2221, 2222, 2223, 2224] [2231, 2232, 2233, 2234] [2241, 2242, 2243, 2244]
 [3211, 3212, 3213, 3214] [3221, 3222, 3223, 3224] [3231, 3232, 3233, 3234] [3241, 3242, 3243, 3244]
 [4211, 4212, 4213, 4214] [4221, 4222, 4223, 4224] [4231, 4232, 4233, 4234] [4241, 4242, 4243, 4244]

 [1311, 1312, 1313, 1314] [1321, 1322, 1323, 1324] [1331, 1332, 1333, 1334] [1341, 1342, 1343, 1344]
 [2311, 2312, 2313, 2314] [2321, 2322, 2323, 2324] [2331, 2332, 2333, 2334] [2341, 2342, 2343, 2344]
 [3311, 3312, 3313, 3314] [3321, 3322, 3323, 3324] [3331, 3332, 3333, 3334] [3341, 3342, 3343, 3344]
 [4311, 4312, 4313, 4314] [4321, 4322, 4323, 4324] [4331, 4332, 4333, 4334] [4341, 4342, 4343, 4344]

 [1411, 1412, 1413, 1414] [1421, 1422, 1423, 1424] [1431, 1432, 1433, 1434] [1441, 1442, 1443, 1444]
 [2411, 2412, 2413, 2414] [2421, 2422, 2423, 2424] [2431, 2432, 2433, 2434] [2441, 2442, 2443, 2444]
 [3411, 3412, 3413, 3414] [3421, 3422, 3423, 3424] [3431, 3432, 3433, 3434] [3441, 3442, 3443, 3444]
 [4411, 4412, 4413, 4414] [4421, 4422, 4423, 4424] [4431, 4432, 4433, 4434] [4441, 4442, 4443, 4444]



 4d matrix :  d4, d2, d3, d1
 ===========================
 [1111, 2111, 3111, 4111] [1211, 2211, 3211, 4211] [1311, 2311, 3311, 4311] [1411, 2411, 3411, 4411]
 [1121, 2121, 3121, 4121] [1221, 2221, 3221, 4221] [1321, 2321, 3321, 4321] [1421, 2421, 3421, 4421]
 [1131, 2131, 3131, 4131] [1231, 2231, 3231, 4231] [1331, 2331, 3331, 4331] [1431, 2431, 3431, 4431]
 [1141, 2141, 3141, 4141] [1241, 2241, 3241, 4241] [1341, 2341, 3341, 4341] [1441, 2441, 3441, 4441]

 [1112, 2112, 3112, 4112] [1212, 2212, 3212, 4212] [1312, 2312, 3312, 4312] [1412, 2412, 3412, 4412]
 [1122, 2122, 3122, 4122] [1222, 2222, 3222, 4222] [1322, 2322, 3322, 4322] [1422, 2422, 3422, 4422]
 [1132, 2132, 3132, 4132] [1232, 2232, 3232, 4232] [1332, 2332, 3332, 4332] [1432, 2432, 3432, 4432]
 [1142, 2142, 3142, 4142] [1242, 2242, 3242, 4242] [1342, 2342, 3342, 4342] [1442, 2442, 3442, 4442]

 [1113, 2113, 3113, 4113] [1213, 2213, 3213, 4213] [1313, 2313, 3313, 4313] [1413, 2413, 3413, 4413]
 [1123, 2123, 3123, 4123] [1223, 2223, 3223, 4223] [1323, 2323, 3323, 4323] [1423, 2423, 3423, 4423]
 [1133, 2133, 3133, 4133] [1233, 2233, 3233, 4233] [1333, 2333, 3333, 4333] [1433, 2433, 3433, 4433]
 [1143, 2143, 3143, 4143] [1243, 2243, 3243, 4243] [1343, 2343, 3343, 4343] [1443, 2443, 3443, 4443]

 [1114, 2114, 3114, 4114] [1214, 2214, 3214, 4214] [1314, 2314, 3314, 4314] [1414, 2414, 3414, 4414]
 [1124, 2124, 3124, 4124] [1224, 2224, 3224, 4224] [1324, 2324, 3324, 4324] [1424, 2424, 3424, 4424]
 [1134, 2134, 3134, 4134] [1234, 2234, 3234, 4234] [1334, 2334, 3334, 4334] [1434, 2434, 3434, 4434]
 [1144, 2144, 3144, 4144] [1244, 2244, 3244, 4244] [1344, 2344, 3344, 4344] [1444, 2444, 3444, 4444]
Alain T.
  • 40,517
  • 4
  • 31
  • 51
0

The lack of direct support for matrix operations in Swift was bothering me so I played around with array extensions and cam up with a few methods that could probably make thing a bit easier.

extension Array
{
   func asMatrix(_ axisSizes: Int ...) -> [Any] { return asMatrix(axisSizes) }
   func asMatrix(_ axisSizes:[Int])    -> [Any]
   {
      if count == 0 { return [] }

      let requiredVectorSize = axisSizes.reduce(1,*)
      let flatData           = asVector
      var newArray:[Any]     = flatData 
      while newArray.count < requiredVectorSize { newArray = newArray + flatData }

      for axisSize in axisSizes.dropFirst().reversed()
      {
         newArray = (0..<newArray.count/axisSize)
                    .map{($0*axisSize,($0+1)*axisSize)}
                    .map{newArray[$0..<$1].map{$0}}
      }
      return newArray   
   }

   var matrixSize:[Int]
   {
      get { return [count] + ((first as? [Any])?.matrixSize ?? []) }
      set { self = asVector.asMatrix(newValue) as! [Element] }
   }

   func vectorIndex(of indexes:[Int]) -> Int
   {
      return zip(matrixSize,indexes).reduce(0){ $0 * $1.0 + $1.1 }      
   }

   func matrixIndex(of vectorIndex:Int) -> [Int]
   {
      var result:[Int] = []
      var vectorIndex  = vectorIndex
      for dim in matrixSize.reversed()
      {
        result.append(vectorIndex % dim)
        vectorIndex = vectorIndex / dim
      } 
      return result.reversed()
   }

   func enumeratedMatrix() -> [([Int],Any)]
   {
      return asVector.enumerated().map{(self.matrixIndex(of:$0),$1)}
   }

   var vectorSize:Int { return matrixSize.reduce(1,*) }

   var asVector:[Any] 
   {
     get { return (self as? [[Any]])?.reduce(Array<Any>()){$0+$1}.asVector ?? self}
     set { self = newValue.asMatrix(matrixSize) as! [Element] }
   }

   subscript(indexes:[Int]) -> Any
   {
      get {  return indexes.reduce(self as Any){ ($0 as! [Any])[$1] } }
      set {  
             if indexes.count == 1 
             { 
               self[indexes.first!] = newValue as! Element
             }
             else 
             {
                var subArray         = self[indexes.first!] as! Array<Any>
                let subIndexes:[Int] = indexes.dropFirst().map{$0}
                subArray[subIndexes] = newValue
                self[indexes.first!] = subArray as! Element
             }
          }
   }

   func transposedMatrix(_ dim1:Int=0, _ dim2:Int=1) -> [Any]
   {
      if dim1 == dim2 { return self }

      var transposedSizes = matrixSize
      swap(&transposedSizes[dim1],&transposedSizes[dim2])

      var indexMap        = (0..<transposedSizes.count).map{$0}
      swap(&indexMap[dim1],&indexMap[dim2])

      let mapping = (0..<vectorSize)
                    .map{($0, matrixIndex(of:$0))}
                    .map{(vi,mi) in (vi,indexMap.map{mi[$0]})}
                    .map{(vi,mi) in (vi,self.vectorIndex(of:mi)) }

      var flatData = asVector

      return mapping
             .sorted{$0.1 < $1.1}
             .map{flatData[$0.0]}
             .asMatrix(transposedSizes)

   }
}

The only issue remaining is that I had to use type erasure so these matrices are treated as arrays or Any and require some type casting for actual use. Nevertheless, it is easier to manipulate them:

// initialized from vectors:
//
let squareNumbers = (0..<64).map{$0}
var chessBoard    = squareNumbers.asMatrix(8,8)

// swapping axes
//
let m4Dim4842 = [0].asMatrix(4,8,4,2)           // 1 element vector is repeated to fill content
let m4Dim2844 = m4Dim4842.transposedMatrix(3,0) // swapped dimensions 0 and 3

// double brackets to access elements
//
let queenPos      = chessBoard[[4,0]] as! Int
chessBoard[[4,0]] = queenPos


// enumeration to traverse all elements
// (and data assignment using a 1d vector)
chessBoard.asVector = chessBoard.enumeratedMatrix().map{$0.0[0]==$0.0[1] ? 1 : 0}
Alain T.
  • 40,517
  • 4
  • 31
  • 51