【问题标题】:Swift: How to swap two axes of a four-dimensional array?Swift:如何交换四维数组的两个轴?
【发布时间】:2026-01-27 08:20:03
【问题描述】:

为了正确地将数据提供给函数,我需要在 Swift 中交换一个四维数组中的两个轴。我想知道如何实现或为此目的是否有任何有用的功能。

在 Python 中,如果我使用 numpy.swapaxes(a, axis1, axis2),则很简单(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

请注意,如果数组是二维的,我可以这样做:

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/

如果您对如何为四维(或更多)阵列进行交换轴有任何想法,请告诉我。感谢您的帮助。

【问题讨论】:

    标签: arrays swift swap


    【解决方案1】:

    最简单的方法是对所有内容进行硬编码,如下所示:

      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
      }
    

    为了减少代码量,你可以通过一个类来改变for循环的顺序。 Change order of for loops?

    【讨论】:

      【解决方案2】:

      为二维矩阵制作转置函数相当容易:

      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]} 
               }
      }
      

      一旦你有了它,任何维度的所有其他转置都可以转换为连续维度上的一系列 2d 转置(基本上交换它们)

      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
      

      重复使用这 3 个基本维度交换,这 4 个维度的所有其他组合都是可能的。

      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 ...
      

      为了帮助测试这一点,我为我在操场上使用的矩阵制作了一个 4d 打印函数:

      它以行列顺序打印,因此您将维度一作为“块”的垂直组,维度 2 作为一列块,维度 3 是每个块的行,维度 4 是每个块的列:

      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]
      

      【讨论】:

        【解决方案3】:

        在 Swift 中缺乏对矩阵运算的直接支持让我很困扰,所以我尝试了数组扩展并想出了一些可能会使事情变得更容易的方法。

        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)
        
           }
        }
        

        剩下的唯一问题是我必须使用类型擦除,因此这些矩阵被视为数组或 Any 并且需要一些类型转换才能实际使用。不过,操作它们更容易:

        // 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}
        

        【讨论】:

          最近更新 更多